@thunderclap-engine/engine 0.0.0-stage → 1.1.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/CHANGELOG.md +390 -0
- package/LICENSE +21 -0
- package/README.md +333 -2
- package/dist/analytics/analytics.d.ts +80 -0
- package/dist/analytics/analytics.js +129 -0
- package/dist/analytics/index.d.ts +1 -0
- package/dist/analytics/index.js +1 -0
- package/dist/anim/aim.d.ts +43 -0
- package/dist/anim/aim.js +157 -0
- package/dist/anim/clip.d.ts +98 -0
- package/dist/anim/clip.js +282 -0
- package/dist/anim/compress.d.ts +65 -0
- package/dist/anim/compress.js +339 -0
- package/dist/anim/foot-ik.d.ts +74 -0
- package/dist/anim/foot-ik.js +241 -0
- package/dist/anim/graph.d.ts +153 -0
- package/dist/anim/graph.js +532 -0
- package/dist/anim/ik.d.ts +105 -0
- package/dist/anim/ik.js +435 -0
- package/dist/anim/index.d.ts +36 -0
- package/dist/anim/index.js +21 -0
- package/dist/anim/match.d.ts +66 -0
- package/dist/anim/match.js +153 -0
- package/dist/anim/mixer.d.ts +113 -0
- package/dist/anim/mixer.js +314 -0
- package/dist/anim/morph.d.ts +41 -0
- package/dist/anim/morph.js +94 -0
- package/dist/anim/pose.d.ts +74 -0
- package/dist/anim/pose.js +254 -0
- package/dist/anim/quat.d.ts +44 -0
- package/dist/anim/quat.js +187 -0
- package/dist/anim/retarget.d.ts +97 -0
- package/dist/anim/retarget.js +366 -0
- package/dist/anim/root-motion.d.ts +44 -0
- package/dist/anim/root-motion.js +224 -0
- package/dist/anim/skin-pose.d.ts +39 -0
- package/dist/anim/skin-pose.js +53 -0
- package/dist/anim/socket.d.ts +47 -0
- package/dist/anim/socket.js +84 -0
- package/dist/anim/spring-chain.d.ts +73 -0
- package/dist/anim/spring-chain.js +294 -0
- package/dist/assets/atlas.d.ts +90 -0
- package/dist/assets/atlas.js +212 -0
- package/dist/assets/baked.d.ts +33 -0
- package/dist/assets/baked.js +38 -0
- package/dist/assets/bundle.d.ts +88 -0
- package/dist/assets/bundle.js +464 -0
- package/dist/assets/cache.d.ts +56 -0
- package/dist/assets/cache.js +123 -0
- package/dist/assets/gltf-load.d.ts +252 -0
- package/dist/assets/gltf-load.js +661 -0
- package/dist/assets/gltf-skin.d.ts +36 -0
- package/dist/assets/gltf-skin.js +109 -0
- package/dist/assets/gltf.d.ts +706 -0
- package/dist/assets/gltf.js +1376 -0
- package/dist/assets/index.d.ts +20 -0
- package/dist/assets/index.js +10 -0
- package/dist/assets/ktx2.d.ts +71 -0
- package/dist/assets/ktx2.js +213 -0
- package/dist/assets/manifest.d.ts +79 -0
- package/dist/assets/manifest.js +7 -0
- package/dist/assets/meshopt.d.ts +23 -0
- package/dist/assets/meshopt.js +403 -0
- package/dist/audio/audio.d.ts +733 -0
- package/dist/audio/audio.js +2013 -0
- package/dist/audio/dsp.d.ts +61 -0
- package/dist/audio/dsp.js +159 -0
- package/dist/audio/duck.d.ts +44 -0
- package/dist/audio/duck.js +101 -0
- package/dist/audio/envelope.d.ts +53 -0
- package/dist/audio/envelope.js +106 -0
- package/dist/audio/index.d.ts +13 -0
- package/dist/audio/index.js +14 -0
- package/dist/audio/music.d.ts +113 -0
- package/dist/audio/music.js +548 -0
- package/dist/audio/occlusion.d.ts +55 -0
- package/dist/audio/occlusion.js +61 -0
- package/dist/audio/persist.d.ts +23 -0
- package/dist/audio/persist.js +27 -0
- package/dist/audio/recipes.d.ts +55 -0
- package/dist/audio/recipes.js +227 -0
- package/dist/audio/send.d.ts +41 -0
- package/dist/audio/send.js +118 -0
- package/dist/audio/sprites.d.ts +59 -0
- package/dist/audio/sprites.js +43 -0
- package/dist/audio/synth.d.ts +103 -0
- package/dist/audio/synth.js +197 -0
- package/dist/audio/variations.d.ts +25 -0
- package/dist/audio/variations.js +55 -0
- package/dist/audio/zones.d.ts +100 -0
- package/dist/audio/zones.js +167 -0
- package/dist/core/detached-surface.d.ts +44 -0
- package/dist/core/detached-surface.js +104 -0
- package/dist/core/events.d.ts +24 -0
- package/dist/core/events.js +43 -0
- package/dist/core/game.d.ts +409 -0
- package/dist/core/game.js +530 -0
- package/dist/core/hash.d.ts +24 -0
- package/dist/core/hash.js +49 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.js +9 -0
- package/dist/core/loop.d.ts +113 -0
- package/dist/core/loop.js +185 -0
- package/dist/core/math.d.ts +58 -0
- package/dist/core/math.js +210 -0
- package/dist/core/noise.d.ts +40 -0
- package/dist/core/noise.js +247 -0
- package/dist/core/pool.d.ts +42 -0
- package/dist/core/pool.js +85 -0
- package/dist/core/random.d.ts +61 -0
- package/dist/core/random.js +199 -0
- package/dist/core/scene.d.ts +79 -0
- package/dist/core/scene.js +195 -0
- package/dist/core/timer.d.ts +66 -0
- package/dist/core/timer.js +286 -0
- package/dist/fx/billboard-wgsl.d.ts +29 -0
- package/dist/fx/billboard-wgsl.js +158 -0
- package/dist/fx/billboard.d.ts +249 -0
- package/dist/fx/billboard.js +702 -0
- package/dist/fx/debug-draw.d.ts +127 -0
- package/dist/fx/debug-draw.js +523 -0
- package/dist/fx/debug-wgsl.d.ts +7 -0
- package/dist/fx/debug-wgsl.js +32 -0
- package/dist/fx/decals-wgsl.d.ts +15 -0
- package/dist/fx/decals-wgsl.js +173 -0
- package/dist/fx/decals.d.ts +216 -0
- package/dist/fx/decals.js +607 -0
- package/dist/fx/effect.d.ts +129 -0
- package/dist/fx/effect.js +349 -0
- package/dist/fx/effects/hit-spark.json +48 -0
- package/dist/fx/effects/index.d.ts +8 -0
- package/dist/fx/effects/index.js +9 -0
- package/dist/fx/effects/magic-aura.json +47 -0
- package/dist/fx/effects/smoke-puff.json +34 -0
- package/dist/fx/emit-surface.d.ts +40 -0
- package/dist/fx/emit-surface.js +124 -0
- package/dist/fx/flicker.d.ts +30 -0
- package/dist/fx/flicker.js +42 -0
- package/dist/fx/index.d.ts +31 -0
- package/dist/fx/index.js +20 -0
- package/dist/fx/particles-wgsl.d.ts +57 -0
- package/dist/fx/particles-wgsl.js +828 -0
- package/dist/fx/particles.d.ts +566 -0
- package/dist/fx/particles.js +1533 -0
- package/dist/fx/random.d.ts +15 -0
- package/dist/fx/random.js +20 -0
- package/dist/fx/sky-wgsl.d.ts +23 -0
- package/dist/fx/sky-wgsl.js +127 -0
- package/dist/fx/sky.d.ts +96 -0
- package/dist/fx/sky.js +175 -0
- package/dist/fx/text-atlas.d.ts +143 -0
- package/dist/fx/text-atlas.js +327 -0
- package/dist/fx/trail-wgsl.d.ts +11 -0
- package/dist/fx/trail-wgsl.js +42 -0
- package/dist/fx/trail.d.ts +194 -0
- package/dist/fx/trail.js +555 -0
- package/dist/fx/water-wgsl.d.ts +34 -0
- package/dist/fx/water-wgsl.js +197 -0
- package/dist/fx/water.d.ts +176 -0
- package/dist/fx/water.js +371 -0
- package/dist/geom/collide/bvh.d.ts +151 -0
- package/dist/geom/collide/bvh.js +493 -0
- package/dist/geom/collide/debug.d.ts +14 -0
- package/dist/geom/collide/debug.js +74 -0
- package/dist/geom/collide/grid.d.ts +26 -0
- package/dist/geom/collide/grid.js +91 -0
- package/dist/geom/collide/index.d.ts +8 -0
- package/dist/geom/collide/index.js +8 -0
- package/dist/geom/collide/queries.d.ts +70 -0
- package/dist/geom/collide/queries.js +583 -0
- package/dist/geom/collide/serialize.d.ts +14 -0
- package/dist/geom/collide/serialize.js +145 -0
- package/dist/geom/collide/shapes.d.ts +161 -0
- package/dist/geom/collide/shapes.js +686 -0
- package/dist/geom/collide/slide.d.ts +66 -0
- package/dist/geom/collide/slide.js +375 -0
- package/dist/geom/collide/tile-slide.d.ts +88 -0
- package/dist/geom/collide/tile-slide.js +255 -0
- package/dist/geom/geometry.d.ts +95 -0
- package/dist/geom/geometry.js +322 -0
- package/dist/geom/heightfield.d.ts +72 -0
- package/dist/geom/heightfield.js +295 -0
- package/dist/geom/hull.d.ts +27 -0
- package/dist/geom/hull.js +279 -0
- package/dist/geom/index.d.ts +35 -0
- package/dist/geom/index.js +23 -0
- package/dist/geom/iso.d.ts +74 -0
- package/dist/geom/iso.js +89 -0
- package/dist/geom/lod.d.ts +29 -0
- package/dist/geom/lod.js +27 -0
- package/dist/geom/ops.d.ts +47 -0
- package/dist/geom/ops.js +285 -0
- package/dist/geom/primitives.d.ts +97 -0
- package/dist/geom/primitives.js +359 -0
- package/dist/geom/shapes.d.ts +43 -0
- package/dist/geom/shapes.js +88 -0
- package/dist/geom/simplify.d.ts +38 -0
- package/dist/geom/simplify.js +519 -0
- package/dist/geom/split.d.ts +37 -0
- package/dist/geom/split.js +413 -0
- package/dist/geom/sweep.d.ts +83 -0
- package/dist/geom/sweep.js +534 -0
- package/dist/geom/tangents.d.ts +16 -0
- package/dist/geom/tangents.js +124 -0
- package/dist/geom/triangulate.d.ts +19 -0
- package/dist/geom/triangulate.js +147 -0
- package/dist/host/default.d.ts +10 -0
- package/dist/host/default.js +10 -0
- package/dist/host/index.d.ts +4 -0
- package/dist/host/index.js +3 -0
- package/dist/host/types.d.ts +144 -0
- package/dist/host/types.js +1 -0
- package/dist/host/web-links.d.ts +38 -0
- package/dist/host/web-links.js +110 -0
- package/dist/host/web.d.ts +30 -0
- package/dist/host/web.js +216 -0
- package/dist/host/xr.d.ts +24 -0
- package/dist/host/xr.js +59 -0
- package/dist/i18n/i18n.d.ts +59 -0
- package/dist/i18n/i18n.js +241 -0
- package/dist/i18n/index.d.ts +3 -0
- package/dist/i18n/index.js +3 -0
- package/dist/i18n/message.d.ts +72 -0
- package/dist/i18n/message.js +369 -0
- package/dist/i18n/negotiate.d.ts +17 -0
- package/dist/i18n/negotiate.js +58 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1 -0
- package/dist/input/bindings.d.ts +31 -0
- package/dist/input/bindings.js +141 -0
- package/dist/input/clock.d.ts +44 -0
- package/dist/input/clock.js +49 -0
- package/dist/input/follow.d.ts +133 -0
- package/dist/input/follow.js +218 -0
- package/dist/input/gestures.d.ts +281 -0
- package/dist/input/gestures.js +662 -0
- package/dist/input/glyphs.d.ts +35 -0
- package/dist/input/glyphs.js +216 -0
- package/dist/input/gyro.d.ts +85 -0
- package/dist/input/gyro.js +140 -0
- package/dist/input/index.d.ts +19 -0
- package/dist/input/index.js +16 -0
- package/dist/input/input.d.ts +543 -0
- package/dist/input/input.js +1492 -0
- package/dist/input/look.d.ts +327 -0
- package/dist/input/look.js +681 -0
- package/dist/input/magnify.d.ts +177 -0
- package/dist/input/magnify.js +131 -0
- package/dist/input/pointer-dispatch.d.ts +138 -0
- package/dist/input/pointer-dispatch.js +180 -0
- package/dist/input/pointer-router.d.ts +204 -0
- package/dist/input/pointer-router.js +533 -0
- package/dist/input/pointer-sources.d.ts +164 -0
- package/dist/input/pointer-sources.js +306 -0
- package/dist/input/rays.d.ts +138 -0
- package/dist/input/rays.js +615 -0
- package/dist/input/record.d.ts +209 -0
- package/dist/input/record.js +601 -0
- package/dist/input/touch-zones.d.ts +147 -0
- package/dist/input/touch-zones.js +300 -0
- package/dist/input/types.d.ts +158 -0
- package/dist/input/types.js +1 -0
- package/dist/input/xr-source.d.ts +53 -0
- package/dist/input/xr-source.js +164 -0
- package/dist/nav/astar.d.ts +45 -0
- package/dist/nav/astar.js +182 -0
- package/dist/nav/corridor.d.ts +40 -0
- package/dist/nav/corridor.js +95 -0
- package/dist/nav/crowd.d.ts +94 -0
- package/dist/nav/crowd.js +624 -0
- package/dist/nav/flow.d.ts +61 -0
- package/dist/nav/flow.js +193 -0
- package/dist/nav/grid.d.ts +108 -0
- package/dist/nav/grid.js +210 -0
- package/dist/nav/heap.d.ts +22 -0
- package/dist/nav/heap.js +92 -0
- package/dist/nav/index.d.ts +37 -0
- package/dist/nav/index.js +19 -0
- package/dist/nav/mesh/areas.d.ts +44 -0
- package/dist/nav/mesh/areas.js +98 -0
- package/dist/nav/mesh/bake-options.d.ts +33 -0
- package/dist/nav/mesh/bake-options.js +76 -0
- package/dist/nav/mesh/contour.d.ts +22 -0
- package/dist/nav/mesh/contour.js +323 -0
- package/dist/nav/mesh/flow3.d.ts +35 -0
- package/dist/nav/mesh/flow3.js +229 -0
- package/dist/nav/mesh/links.d.ts +38 -0
- package/dist/nav/mesh/links.js +72 -0
- package/dist/nav/mesh/mesh-path.d.ts +152 -0
- package/dist/nav/mesh/mesh-path.js +643 -0
- package/dist/nav/mesh/mesh-reach.d.ts +78 -0
- package/dist/nav/mesh/mesh-reach.js +450 -0
- package/dist/nav/mesh/navmesh.d.ts +117 -0
- package/dist/nav/mesh/navmesh.js +647 -0
- package/dist/nav/mesh/polymesh.d.ts +24 -0
- package/dist/nav/mesh/polymesh.js +384 -0
- package/dist/nav/mesh/regions.d.ts +12 -0
- package/dist/nav/mesh/regions.js +367 -0
- package/dist/nav/mesh/serialize.d.ts +13 -0
- package/dist/nav/mesh/serialize.js +197 -0
- package/dist/nav/mesh/voxelize.d.ts +111 -0
- package/dist/nav/mesh/voxelize.js +552 -0
- package/dist/nav/obstacles.d.ts +75 -0
- package/dist/nav/obstacles.js +294 -0
- package/dist/nav/path.d.ts +59 -0
- package/dist/nav/path.js +177 -0
- package/dist/nav/query-queue.d.ts +46 -0
- package/dist/nav/query-queue.js +308 -0
- package/dist/nav/reach.d.ts +53 -0
- package/dist/nav/reach.js +148 -0
- package/dist/nav/steer.d.ts +36 -0
- package/dist/nav/steer.js +78 -0
- package/dist/platform/boot.d.ts +28 -0
- package/dist/platform/boot.js +43 -0
- package/dist/platform/device-mode.d.ts +40 -0
- package/dist/platform/device-mode.js +104 -0
- package/dist/platform/device.d.ts +31 -0
- package/dist/platform/device.js +91 -0
- package/dist/platform/environment.d.ts +42 -0
- package/dist/platform/environment.js +82 -0
- package/dist/platform/gpu.d.ts +40 -0
- package/dist/platform/gpu.js +57 -0
- package/dist/platform/index.d.ts +18 -0
- package/dist/platform/index.js +10 -0
- package/dist/platform/letterbox.d.ts +43 -0
- package/dist/platform/letterbox.js +57 -0
- package/dist/platform/links.d.ts +20 -0
- package/dist/platform/links.js +43 -0
- package/dist/platform/screens.d.ts +36 -0
- package/dist/platform/screens.js +138 -0
- package/dist/platform/surface.d.ts +72 -0
- package/dist/platform/surface.js +157 -0
- package/dist/platform/xr-fake.d.ts +168 -0
- package/dist/platform/xr-fake.js +434 -0
- package/dist/platform/xr-surface.d.ts +120 -0
- package/dist/platform/xr-surface.js +214 -0
- package/dist/platform/xr-types.d.ts +262 -0
- package/dist/post/ao.d.ts +12 -0
- package/dist/post/ao.js +136 -0
- package/dist/post/blend.d.ts +27 -0
- package/dist/post/blend.js +129 -0
- package/dist/post/depth-pass.d.ts +43 -0
- package/dist/post/depth-pass.js +118 -0
- package/dist/post/dof.d.ts +1 -0
- package/dist/post/dof.js +66 -0
- package/dist/post/exposure.d.ts +80 -0
- package/dist/post/exposure.js +322 -0
- package/dist/post/index.d.ts +12 -0
- package/dist/post/index.js +11 -0
- package/dist/post/lens-dirt.d.ts +13 -0
- package/dist/post/lens-dirt.js +91 -0
- package/dist/post/lut.d.ts +19 -0
- package/dist/post/lut.js +50 -0
- package/dist/post/motion-blur.d.ts +9 -0
- package/dist/post/motion-blur.js +78 -0
- package/dist/post/post-stack.d.ts +302 -0
- package/dist/post/post-stack.js +1137 -0
- package/dist/post/settings.d.ts +485 -0
- package/dist/post/settings.js +416 -0
- package/dist/post/shaders.d.ts +25 -0
- package/dist/post/shaders.js +410 -0
- package/dist/post/ssr.d.ts +16 -0
- package/dist/post/ssr.js +155 -0
- package/dist/post/taa.d.ts +74 -0
- package/dist/post/taa.js +235 -0
- package/dist/post/white-balance.d.ts +25 -0
- package/dist/post/white-balance.js +98 -0
- package/dist/render/bindings.d.ts +98 -0
- package/dist/render/bindings.js +281 -0
- package/dist/render/blend.d.ts +13 -0
- package/dist/render/blend.js +26 -0
- package/dist/render/camera-2d.d.ts +72 -0
- package/dist/render/camera-2d.js +92 -0
- package/dist/render/camera.d.ts +302 -0
- package/dist/render/camera.js +671 -0
- package/dist/render/color.d.ts +16 -0
- package/dist/render/color.js +41 -0
- package/dist/render/compressed.d.ts +104 -0
- package/dist/render/compressed.js +248 -0
- package/dist/render/diagnostics.d.ts +15 -0
- package/dist/render/diagnostics.js +43 -0
- package/dist/render/dynamic-resolution.d.ts +70 -0
- package/dist/render/dynamic-resolution.js +126 -0
- package/dist/render/fake-gpu.d.ts +204 -0
- package/dist/render/fake-gpu.js +426 -0
- package/dist/render/flipbook.d.ts +56 -0
- package/dist/render/flipbook.js +87 -0
- package/dist/render/frame.d.ts +278 -0
- package/dist/render/frame.js +174 -0
- package/dist/render/fullscreen.d.ts +54 -0
- package/dist/render/fullscreen.js +91 -0
- package/dist/render/gpu-timer.d.ts +73 -0
- package/dist/render/gpu-timer.js +186 -0
- package/dist/render/index.d.ts +53 -0
- package/dist/render/index.js +29 -0
- package/dist/render/instance-list.d.ts +185 -0
- package/dist/render/instance-list.js +547 -0
- package/dist/render/lights.d.ts +181 -0
- package/dist/render/lights.js +233 -0
- package/dist/render/lod.d.ts +54 -0
- package/dist/render/lod.js +52 -0
- package/dist/render/material.d.ts +165 -0
- package/dist/render/material.js +292 -0
- package/dist/render/mesh.d.ts +284 -0
- package/dist/render/mesh.js +472 -0
- package/dist/render/mipmap.d.ts +16 -0
- package/dist/render/mipmap.js +121 -0
- package/dist/render/parallax.d.ts +50 -0
- package/dist/render/parallax.js +47 -0
- package/dist/render/pbr-wgsl.d.ts +31 -0
- package/dist/render/pbr-wgsl.js +119 -0
- package/dist/render/ping-pong.d.ts +42 -0
- package/dist/render/ping-pong.js +74 -0
- package/dist/render/renderer.d.ts +741 -0
- package/dist/render/renderer.js +2486 -0
- package/dist/render/scene-pipelines.d.ts +44 -0
- package/dist/render/scene-pipelines.js +92 -0
- package/dist/render/scene-target.d.ts +170 -0
- package/dist/render/scene-target.js +450 -0
- package/dist/render/shadow.d.ts +74 -0
- package/dist/render/shadow.js +208 -0
- package/dist/render/skin.d.ts +112 -0
- package/dist/render/skin.js +240 -0
- package/dist/render/snapshot.d.ts +36 -0
- package/dist/render/snapshot.js +34 -0
- package/dist/render/standard.d.ts +162 -0
- package/dist/render/standard.js +263 -0
- package/dist/render/texture.d.ts +142 -0
- package/dist/render/texture.js +228 -0
- package/dist/render/tile-layer.d.ts +110 -0
- package/dist/render/tile-layer.js +304 -0
- package/dist/render/transform.d.ts +115 -0
- package/dist/render/transform.js +318 -0
- package/dist/render/wgsl.d.ts +131 -0
- package/dist/render/wgsl.js +528 -0
- package/dist/save/codec.d.ts +49 -0
- package/dist/save/codec.js +169 -0
- package/dist/save/index.d.ts +8 -0
- package/dist/save/index.js +8 -0
- package/dist/save/journal.d.ts +24 -0
- package/dist/save/journal.js +102 -0
- package/dist/save/migrate.d.ts +15 -0
- package/dist/save/migrate.js +37 -0
- package/dist/save/schema.d.ts +72 -0
- package/dist/save/schema.js +154 -0
- package/dist/save/settings.d.ts +28 -0
- package/dist/save/settings.js +59 -0
- package/dist/save/slots.d.ts +56 -0
- package/dist/save/slots.js +200 -0
- package/dist/save/storage.d.ts +35 -0
- package/dist/save/storage.js +62 -0
- package/dist/save/store.d.ts +114 -0
- package/dist/save/store.js +269 -0
- package/dist/testing/fake-host.d.ts +103 -0
- package/dist/testing/fake-host.js +163 -0
- package/dist/testing/fixed-clock.d.ts +25 -0
- package/dist/testing/fixed-clock.js +30 -0
- package/dist/testing/index.d.ts +4 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/test-game.d.ts +76 -0
- package/dist/testing/test-game.js +92 -0
- package/dist/tween/ease.d.ts +77 -0
- package/dist/tween/ease.js +192 -0
- package/dist/tween/index.d.ts +8 -0
- package/dist/tween/index.js +7 -0
- package/dist/tween/timeline.d.ts +78 -0
- package/dist/tween/timeline.js +269 -0
- package/dist/tween/tween.d.ts +168 -0
- package/dist/tween/tween.js +320 -0
- package/dist/ui/anchor.d.ts +206 -0
- package/dist/ui/anchor.js +307 -0
- package/dist/ui/caption.d.ts +122 -0
- package/dist/ui/caption.js +286 -0
- package/dist/ui/cursor.d.ts +105 -0
- package/dist/ui/cursor.js +261 -0
- package/dist/ui/dom.d.ts +30 -0
- package/dist/ui/dom.js +92 -0
- package/dist/ui/floats.d.ts +86 -0
- package/dist/ui/floats.js +260 -0
- package/dist/ui/hud.d.ts +198 -0
- package/dist/ui/hud.js +431 -0
- package/dist/ui/index.d.ts +37 -0
- package/dist/ui/index.js +34 -0
- package/dist/ui/inventory-card.d.ts +52 -0
- package/dist/ui/inventory-card.js +173 -0
- package/dist/ui/inventory-context.d.ts +29 -0
- package/dist/ui/inventory-context.js +125 -0
- package/dist/ui/inventory-drag.d.ts +63 -0
- package/dist/ui/inventory-drag.js +394 -0
- package/dist/ui/inventory-grid.d.ts +66 -0
- package/dist/ui/inventory-grid.js +625 -0
- package/dist/ui/inventory-radial.d.ts +39 -0
- package/dist/ui/inventory-radial.js +168 -0
- package/dist/ui/inventory.d.ts +128 -0
- package/dist/ui/inventory.js +154 -0
- package/dist/ui/layout.d.ts +356 -0
- package/dist/ui/layout.js +856 -0
- package/dist/ui/link.d.ts +64 -0
- package/dist/ui/link.js +155 -0
- package/dist/ui/loading.d.ts +40 -0
- package/dist/ui/loading.js +157 -0
- package/dist/ui/loupe.d.ts +74 -0
- package/dist/ui/loupe.js +164 -0
- package/dist/ui/menu-nav.d.ts +33 -0
- package/dist/ui/menu-nav.js +28 -0
- package/dist/ui/minimap-canvas.d.ts +145 -0
- package/dist/ui/minimap-canvas.js +460 -0
- package/dist/ui/notify.d.ts +40 -0
- package/dist/ui/notify.js +141 -0
- package/dist/ui/orb.d.ts +53 -0
- package/dist/ui/orb.js +304 -0
- package/dist/ui/overlay.d.ts +213 -0
- package/dist/ui/overlay.js +394 -0
- package/dist/ui/padnav.d.ts +53 -0
- package/dist/ui/padnav.js +146 -0
- package/dist/ui/perf.d.ts +130 -0
- package/dist/ui/perf.js +329 -0
- package/dist/ui/rotate-card.d.ts +54 -0
- package/dist/ui/rotate-card.js +97 -0
- package/dist/ui/stack.d.ts +128 -0
- package/dist/ui/stack.js +312 -0
- package/dist/ui/styles.d.ts +13 -0
- package/dist/ui/styles.js +200 -0
- package/dist/ui/text-scale.d.ts +67 -0
- package/dist/ui/text-scale.js +102 -0
- package/dist/ui/theme.d.ts +70 -0
- package/dist/ui/theme.js +98 -0
- package/dist/ui/toast.d.ts +23 -0
- package/dist/ui/toast.js +46 -0
- package/dist/ui/tooltip.d.ts +89 -0
- package/dist/ui/tooltip.js +333 -0
- package/dist/ui/widgets-2.d.ts +134 -0
- package/dist/ui/widgets-2.js +399 -0
- package/dist/ui/widgets-3.d.ts +91 -0
- package/dist/ui/widgets-3.js +212 -0
- package/dist/ui/widgets.d.ts +34 -0
- package/dist/ui/widgets.js +50 -0
- package/dist/ui/world-panel/index.d.ts +5 -0
- package/dist/ui/world-panel/index.js +5 -0
- package/dist/ui/world-panel/layout.d.ts +38 -0
- package/dist/ui/world-panel/layout.js +68 -0
- package/dist/ui/world-panel/paint.d.ts +96 -0
- package/dist/ui/world-panel/paint.js +136 -0
- package/dist/ui/world-panel/panel.d.ts +235 -0
- package/dist/ui/world-panel/panel.js +762 -0
- package/dist/ui/world-panel/wgsl.d.ts +10 -0
- package/dist/ui/world-panel/wgsl.js +52 -0
- package/dist/ui/world-panel/widgets.d.ts +207 -0
- package/dist/ui/world-panel/widgets.js +569 -0
- package/dist/voxel/chunks.d.ts +77 -0
- package/dist/voxel/chunks.js +149 -0
- package/dist/voxel/grid.d.ts +84 -0
- package/dist/voxel/grid.js +223 -0
- package/dist/voxel/index.d.ts +22 -0
- package/dist/voxel/index.js +7 -0
- package/dist/voxel/mesher-worker.d.ts +14 -0
- package/dist/voxel/mesher-worker.js +47 -0
- package/dist/voxel/mesher.d.ts +73 -0
- package/dist/voxel/mesher.js +306 -0
- package/dist/voxel/ray.d.ts +32 -0
- package/dist/voxel/ray.js +73 -0
- package/dist/voxel/wgsl.d.ts +16 -0
- package/dist/voxel/wgsl.js +28 -0
- package/dist/voxel/worker-client.d.ts +79 -0
- package/dist/voxel/worker-client.js +122 -0
- package/package.json +177 -3
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { createShaderModule } from '../render/wgsl.js';
|
|
2
|
+
export const EXPOSURE_BINS = 64;
|
|
3
|
+
/** log2 luminance of the first bin's lower edge (2^-10 ≈ 0.001). */
|
|
4
|
+
export const EXPOSURE_LOG_MIN = -10;
|
|
5
|
+
/** log2 luminance of the last bin's upper edge (2^6 = 64). */
|
|
6
|
+
export const EXPOSURE_LOG_MAX = 6;
|
|
7
|
+
const LUMA_R = 0.2126;
|
|
8
|
+
const LUMA_G = 0.7152;
|
|
9
|
+
const LUMA_B = 0.0722;
|
|
10
|
+
/** The bin (0..63) a luminance falls in; black and anything under the range land in bin 0. */
|
|
11
|
+
export function exposureBin(luminance) {
|
|
12
|
+
if (!(luminance > 0))
|
|
13
|
+
return 0;
|
|
14
|
+
const t = (Math.log2(luminance) - EXPOSURE_LOG_MIN) / (EXPOSURE_LOG_MAX - EXPOSURE_LOG_MIN);
|
|
15
|
+
return Math.min(EXPOSURE_BINS - 1, Math.max(0, Math.floor(t * EXPOSURE_BINS)));
|
|
16
|
+
}
|
|
17
|
+
/** log2 luminance at the centre of bin `i`. */
|
|
18
|
+
export function exposureBinLog(i) {
|
|
19
|
+
return EXPOSURE_LOG_MIN + ((i + 0.5) / EXPOSURE_BINS) * (EXPOSURE_LOG_MAX - EXPOSURE_LOG_MIN);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* CPU reference of the histogram kernel: `rgba` holds `count` linear RGBA texels (any
|
|
23
|
+
* `ArrayLike`); `out` (64 entries) receives the counts (cleared first).
|
|
24
|
+
*/
|
|
25
|
+
export function exposureHistogram(rgba, count, out = new Uint32Array(EXPOSURE_BINS)) {
|
|
26
|
+
out.fill(0);
|
|
27
|
+
for (let i = 0; i < count; i++) {
|
|
28
|
+
const l = LUMA_R * rgba[i * 4] + LUMA_G * rgba[i * 4 + 1] + LUMA_B * rgba[i * 4 + 2];
|
|
29
|
+
out[exposureBin(l)]++;
|
|
30
|
+
}
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* CPU reference of the average kernel: the mean log2 luminance of the texels between the
|
|
35
|
+
* `low` and `high` percentiles of `hist` (bins partially inside the range count partially).
|
|
36
|
+
* Returns `EXPOSURE_LOG_MIN` for an empty histogram.
|
|
37
|
+
*/
|
|
38
|
+
export function exposureAverage(hist, low, high) {
|
|
39
|
+
let total = 0;
|
|
40
|
+
for (let i = 0; i < EXPOSURE_BINS; i++)
|
|
41
|
+
total += hist[i];
|
|
42
|
+
if (total <= 0)
|
|
43
|
+
return EXPOSURE_LOG_MIN;
|
|
44
|
+
const lo = total * Math.min(1, Math.max(0, low));
|
|
45
|
+
const hi = total * Math.min(1, Math.max(0, high));
|
|
46
|
+
let seen = 0;
|
|
47
|
+
let sum = 0;
|
|
48
|
+
let weight = 0;
|
|
49
|
+
for (let i = 0; i < EXPOSURE_BINS; i++) {
|
|
50
|
+
const n = hist[i];
|
|
51
|
+
const start = seen;
|
|
52
|
+
seen += n;
|
|
53
|
+
// The part of this bin inside [lo, hi].
|
|
54
|
+
const inside = Math.max(0, Math.min(seen, hi) - Math.max(start, lo));
|
|
55
|
+
if (inside > 0) {
|
|
56
|
+
sum += inside * exposureBinLog(i);
|
|
57
|
+
weight += inside;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return weight > 0 ? sum / weight : EXPOSURE_LOG_MIN;
|
|
61
|
+
}
|
|
62
|
+
/** The EV the metered average asks for: `log2(keyValue / average)`, clamped to the range. */
|
|
63
|
+
export function exposureTarget(averageLog, keyValue, minEv, maxEv) {
|
|
64
|
+
const ev = Math.log2(Math.max(keyValue, 1e-6)) - averageLog;
|
|
65
|
+
return Math.min(maxEv, Math.max(minEv, ev));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* One step of the adaptation: `ev` eased toward `target` over `dt` seconds, at `speedUp`
|
|
69
|
+
* per second when rising and `speedDown` when falling (exponential, so it settles without
|
|
70
|
+
* overshoot and a long `dt` lands on the target).
|
|
71
|
+
*/
|
|
72
|
+
export function adaptExposure(ev, target, dt, speedUp, speedDown) {
|
|
73
|
+
const speed = target > ev ? speedUp : speedDown;
|
|
74
|
+
if (!(speed > 0) || !(dt > 0))
|
|
75
|
+
return ev;
|
|
76
|
+
return target + (ev - target) * Math.exp(-speed * dt);
|
|
77
|
+
}
|
|
78
|
+
/** Bytes of the params block the kernels read: low, high, -, - (as f32). */
|
|
79
|
+
const PARAM_FLOATS = 4;
|
|
80
|
+
const HISTOGRAM_WGSL = /* wgsl */ `
|
|
81
|
+
struct Params { low: f32, high: f32, pad0: f32, pad1: f32 };
|
|
82
|
+
@group(0) @binding(0) var colorTex: texture_2d<f32>;
|
|
83
|
+
@group(0) @binding(1) var<storage, read_write> hist: array<atomic<u32>, ${EXPOSURE_BINS}>;
|
|
84
|
+
@group(0) @binding(2) var<uniform> params: Params;
|
|
85
|
+
var<workgroup> local: array<atomic<u32>, ${EXPOSURE_BINS}>;
|
|
86
|
+
|
|
87
|
+
const LOG_MIN: f32 = ${EXPOSURE_LOG_MIN}.0;
|
|
88
|
+
const LOG_RANGE: f32 = ${EXPOSURE_LOG_MAX - EXPOSURE_LOG_MIN}.0;
|
|
89
|
+
|
|
90
|
+
@compute @workgroup_size(16, 16, 1)
|
|
91
|
+
fn main(@builtin(global_invocation_id) gid: vec3u, @builtin(local_invocation_index) li: u32) {
|
|
92
|
+
if (li < ${EXPOSURE_BINS}u) {
|
|
93
|
+
atomicStore(&local[li], 0u);
|
|
94
|
+
}
|
|
95
|
+
workgroupBarrier();
|
|
96
|
+
let dim = textureDimensions(colorTex);
|
|
97
|
+
if (gid.x < dim.x && gid.y < dim.y) {
|
|
98
|
+
let c = textureLoad(colorTex, vec2i(gid.xy), 0).rgb;
|
|
99
|
+
let l = dot(c, vec3f(${LUMA_R}, ${LUMA_G}, ${LUMA_B}));
|
|
100
|
+
var bin = 0u;
|
|
101
|
+
if (l > 0.0) {
|
|
102
|
+
let t = (log2(l) - LOG_MIN) / LOG_RANGE;
|
|
103
|
+
bin = u32(clamp(floor(t * ${EXPOSURE_BINS}.0), 0.0, ${EXPOSURE_BINS - 1}.0));
|
|
104
|
+
}
|
|
105
|
+
atomicAdd(&local[bin], 1u);
|
|
106
|
+
}
|
|
107
|
+
workgroupBarrier();
|
|
108
|
+
if (li < ${EXPOSURE_BINS}u) {
|
|
109
|
+
let n = atomicLoad(&local[li]);
|
|
110
|
+
if (n > 0u) {
|
|
111
|
+
atomicAdd(&hist[li], n);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
`;
|
|
116
|
+
const AVERAGE_WGSL = /* wgsl */ `
|
|
117
|
+
struct Params { low: f32, high: f32, pad0: f32, pad1: f32 };
|
|
118
|
+
@group(0) @binding(0) var<storage, read> hist: array<u32, ${EXPOSURE_BINS}>;
|
|
119
|
+
@group(0) @binding(1) var<storage, read_write> result: vec4f;
|
|
120
|
+
@group(0) @binding(2) var<uniform> params: Params;
|
|
121
|
+
|
|
122
|
+
const LOG_MIN: f32 = ${EXPOSURE_LOG_MIN}.0;
|
|
123
|
+
const LOG_RANGE: f32 = ${EXPOSURE_LOG_MAX - EXPOSURE_LOG_MIN}.0;
|
|
124
|
+
|
|
125
|
+
@compute @workgroup_size(1, 1, 1)
|
|
126
|
+
fn main() {
|
|
127
|
+
var total = 0.0;
|
|
128
|
+
for (var i = 0u; i < ${EXPOSURE_BINS}u; i++) {
|
|
129
|
+
total += f32(hist[i]);
|
|
130
|
+
}
|
|
131
|
+
if (total <= 0.0) {
|
|
132
|
+
result = vec4f(LOG_MIN, 0.0, 0.0, 0.0);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
let lo = total * clamp(params.low, 0.0, 1.0);
|
|
136
|
+
let hi = total * clamp(params.high, 0.0, 1.0);
|
|
137
|
+
var seen = 0.0;
|
|
138
|
+
var sum = 0.0;
|
|
139
|
+
var weight = 0.0;
|
|
140
|
+
for (var i = 0u; i < ${EXPOSURE_BINS}u; i++) {
|
|
141
|
+
let n = f32(hist[i]);
|
|
142
|
+
let start = seen;
|
|
143
|
+
seen += n;
|
|
144
|
+
let inside = max(0.0, min(seen, hi) - max(start, lo));
|
|
145
|
+
if (inside > 0.0) {
|
|
146
|
+
sum += inside * (LOG_MIN + ((f32(i) + 0.5) / ${EXPOSURE_BINS}.0) * LOG_RANGE);
|
|
147
|
+
weight += inside;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
var avg = LOG_MIN;
|
|
151
|
+
if (weight > 0.0) {
|
|
152
|
+
avg = sum / weight;
|
|
153
|
+
}
|
|
154
|
+
result = vec4f(avg, total, 0.0, 0.0);
|
|
155
|
+
}
|
|
156
|
+
`;
|
|
157
|
+
/**
|
|
158
|
+
* The two compute passes and their buffers. `encode` records both (clearing the histogram
|
|
159
|
+
* first) and the copy into the readback buffer; `poll` maps it when free and stores the last
|
|
160
|
+
* average in `averageLog`. On a device without `mapAsync` (the fake one) nothing is read back.
|
|
161
|
+
*/
|
|
162
|
+
export class ExposurePasses {
|
|
163
|
+
device;
|
|
164
|
+
histogram;
|
|
165
|
+
average;
|
|
166
|
+
histLayout;
|
|
167
|
+
histBuffer;
|
|
168
|
+
resultBuffer;
|
|
169
|
+
readBuffer;
|
|
170
|
+
params;
|
|
171
|
+
paramData = new Float32Array(PARAM_FLOATS);
|
|
172
|
+
averageGroup;
|
|
173
|
+
histGroup = null;
|
|
174
|
+
boundColor = null;
|
|
175
|
+
histDesc = { label: 'pass:post-exposure-histogram' };
|
|
176
|
+
avgDesc = { label: 'pass:post-exposure-average' };
|
|
177
|
+
/** A copy into the readback buffer is in flight (the next `poll` may map it). */
|
|
178
|
+
pending = false;
|
|
179
|
+
mapping = false;
|
|
180
|
+
/** The last metered average log2 luminance (`EXPOSURE_LOG_MIN` until the first readback). */
|
|
181
|
+
averageLog = EXPOSURE_LOG_MIN;
|
|
182
|
+
/** How many readbacks have landed. */
|
|
183
|
+
readbacks = 0;
|
|
184
|
+
onMapped;
|
|
185
|
+
onMapFailed;
|
|
186
|
+
constructor(renderer) {
|
|
187
|
+
const device = renderer.device;
|
|
188
|
+
this.device = device;
|
|
189
|
+
const compute = GPUShaderStage.COMPUTE;
|
|
190
|
+
this.histLayout = device.createBindGroupLayout({
|
|
191
|
+
label: 'pass:post-exposure-histogram',
|
|
192
|
+
entries: [
|
|
193
|
+
{ binding: 0, visibility: compute, texture: { sampleType: 'unfilterable-float' } },
|
|
194
|
+
{ binding: 1, visibility: compute, buffer: { type: 'storage' } },
|
|
195
|
+
{ binding: 2, visibility: compute, buffer: {} },
|
|
196
|
+
],
|
|
197
|
+
});
|
|
198
|
+
const avgLayout = device.createBindGroupLayout({
|
|
199
|
+
label: 'pass:post-exposure-average',
|
|
200
|
+
entries: [
|
|
201
|
+
{ binding: 0, visibility: compute, buffer: { type: 'read-only-storage' } },
|
|
202
|
+
{ binding: 1, visibility: compute, buffer: { type: 'storage' } },
|
|
203
|
+
{ binding: 2, visibility: compute, buffer: {} },
|
|
204
|
+
],
|
|
205
|
+
});
|
|
206
|
+
this.histogram = device.createComputePipeline({
|
|
207
|
+
label: 'pass:post-exposure-histogram',
|
|
208
|
+
layout: device.createPipelineLayout({ bindGroupLayouts: [this.histLayout] }),
|
|
209
|
+
compute: {
|
|
210
|
+
module: createShaderModule(device, HISTOGRAM_WGSL, 'pass:post-exposure-histogram'),
|
|
211
|
+
entryPoint: 'main',
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
this.average = device.createComputePipeline({
|
|
215
|
+
label: 'pass:post-exposure-average',
|
|
216
|
+
layout: device.createPipelineLayout({ bindGroupLayouts: [avgLayout] }),
|
|
217
|
+
compute: {
|
|
218
|
+
module: createShaderModule(device, AVERAGE_WGSL, 'pass:post-exposure-average'),
|
|
219
|
+
entryPoint: 'main',
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
this.histBuffer = device.createBuffer({
|
|
223
|
+
label: 'post-exposure-histogram',
|
|
224
|
+
size: EXPOSURE_BINS * 4,
|
|
225
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
|
|
226
|
+
});
|
|
227
|
+
this.resultBuffer = device.createBuffer({
|
|
228
|
+
label: 'post-exposure-average',
|
|
229
|
+
size: 16,
|
|
230
|
+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
|
|
231
|
+
});
|
|
232
|
+
this.readBuffer = device.createBuffer({
|
|
233
|
+
label: 'post-exposure-readback',
|
|
234
|
+
size: 16,
|
|
235
|
+
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
|
|
236
|
+
});
|
|
237
|
+
this.params = device.createBuffer({
|
|
238
|
+
label: 'post-exposure-params',
|
|
239
|
+
size: PARAM_FLOATS * 4,
|
|
240
|
+
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
241
|
+
});
|
|
242
|
+
this.averageGroup = device.createBindGroup({
|
|
243
|
+
label: 'pass:post-exposure-average',
|
|
244
|
+
layout: avgLayout,
|
|
245
|
+
entries: [
|
|
246
|
+
{ binding: 0, resource: { buffer: this.histBuffer } },
|
|
247
|
+
{ binding: 1, resource: { buffer: this.resultBuffer } },
|
|
248
|
+
{ binding: 2, resource: { buffer: this.params } },
|
|
249
|
+
],
|
|
250
|
+
});
|
|
251
|
+
this.onMapped = () => {
|
|
252
|
+
const data = new Float32Array(this.readBuffer.getMappedRange());
|
|
253
|
+
this.averageLog = data[0];
|
|
254
|
+
this.readBuffer.unmap();
|
|
255
|
+
this.mapping = false;
|
|
256
|
+
this.pending = false;
|
|
257
|
+
this.readbacks++;
|
|
258
|
+
};
|
|
259
|
+
this.onMapFailed = () => {
|
|
260
|
+
this.mapping = false;
|
|
261
|
+
this.pending = false;
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Map the last copy if one is waiting and the buffer is free (call before `encode`, once the
|
|
266
|
+
* previous frame's work has been submitted).
|
|
267
|
+
*/
|
|
268
|
+
poll() {
|
|
269
|
+
if (!this.pending || this.mapping)
|
|
270
|
+
return;
|
|
271
|
+
if (typeof this.readBuffer.mapAsync !== 'function')
|
|
272
|
+
return;
|
|
273
|
+
if (this.readBuffer.mapState !== 'unmapped')
|
|
274
|
+
return;
|
|
275
|
+
this.mapping = true;
|
|
276
|
+
this.readBuffer.mapAsync(GPUMapMode.READ).then(this.onMapped, this.onMapFailed);
|
|
277
|
+
}
|
|
278
|
+
/** Record the histogram, the average and (when the readback buffer is free) the copy. */
|
|
279
|
+
encode(encoder, color, width, height, low, high) {
|
|
280
|
+
if (color !== this.boundColor) {
|
|
281
|
+
this.boundColor = color;
|
|
282
|
+
this.histGroup = this.device.createBindGroup({
|
|
283
|
+
label: 'pass:post-exposure-histogram',
|
|
284
|
+
layout: this.histLayout,
|
|
285
|
+
entries: [
|
|
286
|
+
{ binding: 0, resource: color },
|
|
287
|
+
{ binding: 1, resource: { buffer: this.histBuffer } },
|
|
288
|
+
{ binding: 2, resource: { buffer: this.params } },
|
|
289
|
+
],
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
this.paramData[0] = low;
|
|
293
|
+
this.paramData[1] = high;
|
|
294
|
+
this.device.queue.writeBuffer(this.params, 0, this.paramData);
|
|
295
|
+
encoder.clearBuffer(this.histBuffer);
|
|
296
|
+
const h = encoder.beginComputePass(this.histDesc);
|
|
297
|
+
h.setPipeline(this.histogram);
|
|
298
|
+
h.setBindGroup(0, this.histGroup);
|
|
299
|
+
h.dispatchWorkgroups(Math.ceil(width / 16), Math.ceil(height / 16));
|
|
300
|
+
h.end();
|
|
301
|
+
const a = encoder.beginComputePass(this.avgDesc);
|
|
302
|
+
a.setPipeline(this.average);
|
|
303
|
+
a.setBindGroup(0, this.averageGroup);
|
|
304
|
+
a.dispatchWorkgroups(1);
|
|
305
|
+
a.end();
|
|
306
|
+
if (!this.pending) {
|
|
307
|
+
encoder.copyBufferToBuffer(this.resultBuffer, 0, this.readBuffer, 0, 16);
|
|
308
|
+
this.pending = true;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/** Forget a stale bind group (the colour texture was replaced). */
|
|
312
|
+
invalidate() {
|
|
313
|
+
this.boundColor = null;
|
|
314
|
+
this.histGroup = null;
|
|
315
|
+
}
|
|
316
|
+
destroy() {
|
|
317
|
+
this.histBuffer.destroy();
|
|
318
|
+
this.resultBuffer.destroy();
|
|
319
|
+
this.readBuffer.destroy();
|
|
320
|
+
this.params.destroy();
|
|
321
|
+
}
|
|
322
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { aoProjectedRadius } from './ao.js';
|
|
2
|
+
export { type Ease, easeIn, easeInOut, easeLinear, easeOut, PostBlender } from './blend.js';
|
|
3
|
+
export { adaptExposure, EXPOSURE_BINS, EXPOSURE_LOG_MAX, EXPOSURE_LOG_MIN, exposureAverage, exposureBin, exposureBinLog, exposureHistogram, exposureTarget, } from './exposure.js';
|
|
4
|
+
export { createLensDirtTexture, lensDirtTexels } from './lens-dirt.js';
|
|
5
|
+
export { createLutTexture, identityLut, type LutFn, type LutSize, lutTexels } from './lut.js';
|
|
6
|
+
export { motionVelocity } from './motion-blur.js';
|
|
7
|
+
export { PostStack } from './post-stack.js';
|
|
8
|
+
export type { AberrationSettings, AoSettings, BloomSettings, DofSettings, ExposureSettings, FxaaSettings, GodRaySettings, GradeSettings, GrainSettings, LensDirtSettings, LutSettings, MistSettings, MotionBlurMode, MotionBlurSettings, OutlineSettings, PostFrameState, PostQuality, PostQualityTier, PostSettings, PostSettingsPatch, RGB, SharpenSettings, SsrSettings, TaaHistoryFilter, TaaReprojection, TaaSettings, Tonemap, VignetteSettings, WhiteBalanceSettings, } from './settings.js';
|
|
9
|
+
export { applyPostPatch, cinematicPostSettings, clonePostSettings, defaultPostQuality, godRaySource, lowPostQuality, neutralPostSettings, postQualityFor, } from './settings.js';
|
|
10
|
+
export { ssrEdgeFade, ssrRoughnessFade, ssrStep, ssrSurfaceWeight } from './ssr.js';
|
|
11
|
+
export { halton, TAA_AUX_FORMAT, TAA_MAX_FEEDBACK, Taa, taaBlendWeight, taaCatmullRomWeights, taaRejects, taaReprojection, } from './taa.js';
|
|
12
|
+
export { planckianXy, whiteBalanceMatrix } from './white-balance.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { aoProjectedRadius } from './ao.js';
|
|
2
|
+
export { easeIn, easeInOut, easeLinear, easeOut, PostBlender } from './blend.js';
|
|
3
|
+
export { adaptExposure, EXPOSURE_BINS, EXPOSURE_LOG_MAX, EXPOSURE_LOG_MIN, exposureAverage, exposureBin, exposureBinLog, exposureHistogram, exposureTarget, } from './exposure.js';
|
|
4
|
+
export { createLensDirtTexture, lensDirtTexels } from './lens-dirt.js';
|
|
5
|
+
export { createLutTexture, identityLut, lutTexels } from './lut.js';
|
|
6
|
+
export { motionVelocity } from './motion-blur.js';
|
|
7
|
+
export { PostStack } from './post-stack.js';
|
|
8
|
+
export { applyPostPatch, cinematicPostSettings, clonePostSettings, defaultPostQuality, godRaySource, lowPostQuality, neutralPostSettings, postQualityFor, } from './settings.js';
|
|
9
|
+
export { ssrEdgeFade, ssrRoughnessFade, ssrStep, ssrSurfaceWeight } from './ssr.js';
|
|
10
|
+
export { halton, TAA_AUX_FORMAT, TAA_MAX_FEEDBACK, Taa, taaBlendWeight, taaCatmullRomWeights, taaRejects, taaReprojection, } from './taa.js';
|
|
11
|
+
export { planckianXy, whiteBalanceMatrix } from './white-balance.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lens dirt (ws/post-3): a procedural `rgba8unorm` texture of speckles and smudges the
|
|
3
|
+
* composite multiplies into the bloom term (`bloom × (1 + dirt × intensity)`). Pass it as
|
|
4
|
+
* `settings.bloom.dirt = { texture, intensity }`.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* The texels of a `size × size` dirt map (rgba8, greyscale, alpha 255), deterministic in
|
|
8
|
+
* `seed`: ~`size / 2` soft speckles of a few px and a handful of long faint smudges, strongest
|
|
9
|
+
* toward the corners so the centre of the frame stays clean.
|
|
10
|
+
*/
|
|
11
|
+
export declare function lensDirtTexels(size: number, seed: number): Uint8Array;
|
|
12
|
+
/** A `size × size` `rgba8unorm` dirt texture on `device` (uploaded once; destroy it yourself). */
|
|
13
|
+
export declare function createLensDirtTexture(device: GPUDevice, size?: number, seed?: number): GPUTexture;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lens dirt (ws/post-3): a procedural `rgba8unorm` texture of speckles and smudges the
|
|
3
|
+
* composite multiplies into the bloom term (`bloom × (1 + dirt × intensity)`). Pass it as
|
|
4
|
+
* `settings.bloom.dirt = { texture, intensity }`.
|
|
5
|
+
*/
|
|
6
|
+
function hash(seed, i) {
|
|
7
|
+
// Two rounds of a 32-bit integer mix; returns 0..1.
|
|
8
|
+
let x = (Math.imul(seed | 0, 0x9e3779b1) ^ Math.imul(i + 1, 0x85ebca6b)) >>> 0;
|
|
9
|
+
x = Math.imul(x ^ (x >>> 15), 0x2c1b3c6d) >>> 0;
|
|
10
|
+
x = Math.imul(x ^ (x >>> 12), 0x297a2d39) >>> 0;
|
|
11
|
+
return ((x ^ (x >>> 15)) >>> 0) / 4294967296;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The texels of a `size × size` dirt map (rgba8, greyscale, alpha 255), deterministic in
|
|
15
|
+
* `seed`: ~`size / 2` soft speckles of a few px and a handful of long faint smudges, strongest
|
|
16
|
+
* toward the corners so the centre of the frame stays clean.
|
|
17
|
+
*/
|
|
18
|
+
export function lensDirtTexels(size, seed) {
|
|
19
|
+
const n = Math.max(1, Math.floor(size));
|
|
20
|
+
const img = new Float32Array(n * n);
|
|
21
|
+
let k = 0;
|
|
22
|
+
const speckles = Math.max(4, n >> 1);
|
|
23
|
+
for (let i = 0; i < speckles; i++) {
|
|
24
|
+
const cx = hash(seed, k++) * n;
|
|
25
|
+
const cy = hash(seed, k++) * n;
|
|
26
|
+
const r = 0.5 + hash(seed, k++) * hash(seed, k++) * (n / 40);
|
|
27
|
+
const a = 0.3 + hash(seed, k++) * 0.7;
|
|
28
|
+
stamp(img, n, cx, cy, r, r, 0, a);
|
|
29
|
+
}
|
|
30
|
+
const smudges = 6 + Math.floor(hash(seed, k++) * 6);
|
|
31
|
+
for (let i = 0; i < smudges; i++) {
|
|
32
|
+
const cx = hash(seed, k++) * n;
|
|
33
|
+
const cy = hash(seed, k++) * n;
|
|
34
|
+
const len = n * (0.08 + hash(seed, k++) * 0.2);
|
|
35
|
+
const wid = n * (0.01 + hash(seed, k++) * 0.02);
|
|
36
|
+
const ang = hash(seed, k++) * Math.PI;
|
|
37
|
+
stamp(img, n, cx, cy, len, wid, ang, 0.08 + hash(seed, k++) * 0.12);
|
|
38
|
+
}
|
|
39
|
+
const out = new Uint8Array(n * n * 4);
|
|
40
|
+
for (let y = 0; y < n; y++) {
|
|
41
|
+
for (let x = 0; x < n; x++) {
|
|
42
|
+
// Vignette the dirt: full at the corners, a third in the centre.
|
|
43
|
+
const dx = (x + 0.5) / n - 0.5;
|
|
44
|
+
const dy = (y + 0.5) / n - 0.5;
|
|
45
|
+
const edge = 0.35 + 0.65 * Math.min(1, Math.hypot(dx, dy) * 1.6);
|
|
46
|
+
const v = Math.round(Math.min(1, img[y * n + x] * edge) * 255);
|
|
47
|
+
const o = (y * n + x) * 4;
|
|
48
|
+
out[o] = v;
|
|
49
|
+
out[o + 1] = v;
|
|
50
|
+
out[o + 2] = v;
|
|
51
|
+
out[o + 3] = 255;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
/** Add a soft ellipse (`rx` along `angle`, `ry` across) of peak `amount` at `(cx, cy)`. */
|
|
57
|
+
function stamp(img, n, cx, cy, rx, ry, angle, amount) {
|
|
58
|
+
const reach = Math.ceil(Math.max(rx, ry)) + 1;
|
|
59
|
+
const x0 = Math.max(0, Math.floor(cx - reach));
|
|
60
|
+
const x1 = Math.min(n - 1, Math.ceil(cx + reach));
|
|
61
|
+
const y0 = Math.max(0, Math.floor(cy - reach));
|
|
62
|
+
const y1 = Math.min(n - 1, Math.ceil(cy + reach));
|
|
63
|
+
const c = Math.cos(angle);
|
|
64
|
+
const s = Math.sin(angle);
|
|
65
|
+
for (let y = y0; y <= y1; y++) {
|
|
66
|
+
for (let x = x0; x <= x1; x++) {
|
|
67
|
+
const dx = x + 0.5 - cx;
|
|
68
|
+
const dy = y + 0.5 - cy;
|
|
69
|
+
const u = (dx * c + dy * s) / rx;
|
|
70
|
+
const v = (-dx * s + dy * c) / ry;
|
|
71
|
+
const d = u * u + v * v;
|
|
72
|
+
if (d >= 1)
|
|
73
|
+
continue;
|
|
74
|
+
const f = 1 - d;
|
|
75
|
+
img[y * n + x] = Math.min(1, img[y * n + x] + amount * f * f);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** A `size × size` `rgba8unorm` dirt texture on `device` (uploaded once; destroy it yourself). */
|
|
80
|
+
export function createLensDirtTexture(device, size = 256, seed = 1) {
|
|
81
|
+
const n = Math.max(1, Math.floor(size));
|
|
82
|
+
const texture = device.createTexture({
|
|
83
|
+
label: 'post-lens-dirt',
|
|
84
|
+
size: [n, n],
|
|
85
|
+
format: 'rgba8unorm',
|
|
86
|
+
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
|
|
87
|
+
});
|
|
88
|
+
const texels = lensDirtTexels(n, seed);
|
|
89
|
+
device.queue.writeTexture({ texture }, texels, { bytesPerRow: n * 4, rowsPerImage: n }, [n, n]);
|
|
90
|
+
return texture;
|
|
91
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 3D colour lookup tables for `PostSettings.lut` (ws/post-2): a `size`³ `rgba8unorm` texture
|
|
3
|
+
* the composite samples trilinearly with the graded colour as the coordinate (red along x,
|
|
4
|
+
* green along y, blue along z). Build one from a function with `createLutTexture`, or start
|
|
5
|
+
* from `identityLut` and edit its texels.
|
|
6
|
+
*/
|
|
7
|
+
export type LutSize = 16 | 32;
|
|
8
|
+
/** Maps an input colour (each 0..1) to an output colour (each 0..1, clamped on write). */
|
|
9
|
+
export type LutFn = (r: number, g: number, b: number) => readonly [number, number, number];
|
|
10
|
+
/**
|
|
11
|
+
* The texels `createLutTexture` uploads: `size`³ RGBA8 values, red fastest, then green, then
|
|
12
|
+
* blue (one `size`×`size` slice per blue step). Exported so a LUT can be checked or edited on the
|
|
13
|
+
* CPU before upload.
|
|
14
|
+
*/
|
|
15
|
+
export declare function lutTexels(size: LutSize, fn: LutFn): Uint8Array;
|
|
16
|
+
/** Make and upload a `size`³ LUT from `fn`. Destroy it with `texture.destroy()` when done. */
|
|
17
|
+
export declare function createLutTexture(device: GPUDevice, size: LutSize, fn: LutFn): GPUTexture;
|
|
18
|
+
/** A LUT that leaves colours alone: the starting point for a graded one. */
|
|
19
|
+
export declare function identityLut(device: GPUDevice, size: LutSize): GPUTexture;
|
package/dist/post/lut.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 3D colour lookup tables for `PostSettings.lut` (ws/post-2): a `size`³ `rgba8unorm` texture
|
|
3
|
+
* the composite samples trilinearly with the graded colour as the coordinate (red along x,
|
|
4
|
+
* green along y, blue along z). Build one from a function with `createLutTexture`, or start
|
|
5
|
+
* from `identityLut` and edit its texels.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* The texels `createLutTexture` uploads: `size`³ RGBA8 values, red fastest, then green, then
|
|
9
|
+
* blue (one `size`×`size` slice per blue step). Exported so a LUT can be checked or edited on the
|
|
10
|
+
* CPU before upload.
|
|
11
|
+
*/
|
|
12
|
+
export function lutTexels(size, fn) {
|
|
13
|
+
const n = size;
|
|
14
|
+
const out = new Uint8Array(n * n * n * 4);
|
|
15
|
+
const step = 1 / (n - 1);
|
|
16
|
+
let o = 0;
|
|
17
|
+
for (let b = 0; b < n; b++) {
|
|
18
|
+
for (let g = 0; g < n; g++) {
|
|
19
|
+
for (let r = 0; r < n; r++) {
|
|
20
|
+
const c = fn(r * step, g * step, b * step);
|
|
21
|
+
out[o] = quantize(c[0]);
|
|
22
|
+
out[o + 1] = quantize(c[1]);
|
|
23
|
+
out[o + 2] = quantize(c[2]);
|
|
24
|
+
out[o + 3] = 255;
|
|
25
|
+
o += 4;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
/** Make and upload a `size`³ LUT from `fn`. Destroy it with `texture.destroy()` when done. */
|
|
32
|
+
export function createLutTexture(device, size, fn) {
|
|
33
|
+
const texture = device.createTexture({
|
|
34
|
+
label: 'post-lut',
|
|
35
|
+
size: [size, size, size],
|
|
36
|
+
dimension: '3d',
|
|
37
|
+
format: 'rgba8unorm',
|
|
38
|
+
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
|
|
39
|
+
});
|
|
40
|
+
device.queue.writeTexture({ texture }, lutTexels(size, fn), { bytesPerRow: size * 4, rowsPerImage: size }, [size, size, size]);
|
|
41
|
+
return texture;
|
|
42
|
+
}
|
|
43
|
+
/** A LUT that leaves colours alone: the starting point for a graded one. */
|
|
44
|
+
export function identityLut(device, size) {
|
|
45
|
+
return createLutTexture(device, size, identity);
|
|
46
|
+
}
|
|
47
|
+
const identity = (r, g, b) => [r, g, b];
|
|
48
|
+
function quantize(v) {
|
|
49
|
+
return Math.round(Math.min(1, Math.max(0, v)) * 255);
|
|
50
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The screen-space velocity (uv units, +x right, +y down) of the pixel at `(u, v)` with clip
|
|
3
|
+
* depth `depth`, through `reproj` (current clip → previous clip): where the point was minus
|
|
4
|
+
* where it is. Written to `out[0..1]`; the shader's `velocity` does the same.
|
|
5
|
+
*/
|
|
6
|
+
export declare function motionVelocity(out: {
|
|
7
|
+
[i: number]: number;
|
|
8
|
+
}, reproj: ArrayLike<number>, u: number, v: number, depth: number): typeof out;
|
|
9
|
+
export declare const MOTION_BLUR_WGSL = "\n\nstruct PostUniforms {\n frame: vec4f, // time, aspect, 1/width, 1/height\n enables: vec4f, // bloom, fog, rays, vignette\n enables2: vec4f, // grade, tonemap (0 none, 1 aces, 2 reinhard), dither, exposure\n bloom: vec4f, // intensity, threshold, knee, emissiveWeight\n bloom2: vec4f, // scatter, -, -, -\n fogColor: vec4f, // rgb, density\n fog: vec4f, // top, bottom, noiseScale, speed\n fog2: vec4f, // lightScatter, falloff, -, -\n rays: vec4f, // light uv x, y, intensity, decay\n rays2: vec4f, // density, weight, source radius (uv-y units), source intensity\n raysColor: vec4f, // rgb, bloomSource\n vignette: vec4f, // intensity, radius, softness, -\n vignetteColor: vec4f,\n lift: vec4f,\n gamma: vec4f,\n gain: vec4f,\n grade: vec4f, // saturation, contrast, -, -\n quality: vec4f, // ray samples, fog octaves, ortho projection (1, ws/post-4), -\n ao: vec4f, // enabled (0 without depth), radius, intensity, bias\n ao2: vec4f, // power, samples, proj x scale, proj y scale\n dof: vec4f, // enabled (0 without depth), focus distance, focus range, max blur (uv of width)\n dof2: vec4f, // near blur, taps, near plane, far plane\n invProj: mat4x4f, // clip -> view\n fxaa: vec4f, // enabled, subpixel, edgeThreshold, -\n lut: vec4f, // enabled, (size-1)/size, intensity, 0.5/size\n grain: vec4f, // intensity, cell size (px), luminanceResponse, seed\n aberration: vec4f, // intensity (px), radialOnly, -, -\n sharpen: vec4f, // amount, -, -, -\n outline: vec4f, // enabled (0 without depth), thickness (scene px), depthThreshold, normalThreshold\n outlineColor: vec4f, // rgb, intensity\n // Post 3 (ws/post-3).\n taa: vec4f, // enabled (0 without depth), feedback, sharpen, clampMode (0 aabb, 1 variance)\n taa2: vec4f, // view jitter x (uv), view jitter y (uv), reset (1 = copy the current frame), velocity reprojection (1, ws/post-5)\n ssr: vec4f, // enabled (0 without depth), maxSteps, thickness, maxDistance\n ssr2: vec4f, // roughnessCutoff, intensity, fadeEdges (uv), rough-metal target (1)\n exposure: vec4f, // auto (1), histogramLow, histogramHigh, keyValue\n wb0: vec4f, // white-balance matrix row 0 (rgb weights), enabled\n wb1: vec4f, // row 1\n wb2: vec4f, // row 2\n motionBlur: vec4f, // enabled (0 without depth), intensity, samples, velocity target (1 = object)\n dirt: vec4f, // enabled, intensity, -, -\n reproj: mat4x4f, // current clip -> previous frame's clip (identity on a reset)\n // Post 5 (ws/post-5).\n taa3: vec4f, // depthReject (fraction), velocityReject (px), history filter (1 = Catmull-Rom, ws/post-6), -\n};\n@group(0) @binding(0) var<uniform> P: PostUniforms;\n\n@group(0) @binding(1) var nearest: sampler;\n@group(0) @binding(2) var linSamp: sampler;\n@group(0) @binding(3) var depthTex: texture_depth_2d;\n@group(0) @binding(4) var colorTex: texture_2d<f32>;\n@group(0) @binding(5) var velocityTex: texture_2d<f32>;\n\nfn velocity(uv: vec2f, d: f32) -> vec2f {\n let prev = P.reproj * vec4f(uv.x * 2.0 - 1.0, 1.0 - uv.y * 2.0, d, 1.0);\n if (prev.w <= 0.0) {\n return vec2f(0.0);\n }\n let pn = prev.xy / prev.w;\n return vec2f(pn.x * 0.5 + 0.5, 0.5 - pn.y * 0.5) - uv;\n}\n\n@fragment fn fs_main(in: FullscreenIn) -> @location(0) vec4f {\n let uv = in.uv;\n let d = textureSampleLevel(depthTex, nearest, uv, 0u);\n var v = vec2f(0.0);\n if (P.motionBlur.w > 0.5) {\n // The target holds where the pixel is minus where it was; the gather is symmetric, but keep\n // the camera path's sign (where it was minus where it is).\n v = -textureSampleLevel(velocityTex, nearest, uv, 0.0).xy;\n }\n if (dot(v, v) < 1e-12) {\n v = velocity(uv, d);\n }\n var vel = v * P.motionBlur.y;\n // Cap the smear at a tenth of the screen so a teleport does not wipe the frame.\n let len = length(vel);\n if (len > 0.1) {\n vel *= 0.1 / len;\n }\n let n = i32(P.motionBlur.z);\n var sum = vec3f(0.0);\n for (var i = 0; i < n; i++) {\n let f = (f32(i) + 0.5) / f32(n) - 0.5;\n sum += textureSampleLevel(colorTex, linSamp, uv + vel * f, 0.0).rgb;\n }\n return vec4f(sum / f32(n), 1.0);\n}\n";
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Motion blur (ws/post-3, object velocity since ws/post-4): a scene-size `DepthPass` that
|
|
3
|
+
* averages `P.motionBlur.z` taps of the scene colour along each pixel's velocity, scaled by
|
|
4
|
+
* `P.motionBlur.y`. The composite reads the result as its scene colour, so the blur sits
|
|
5
|
+
* before bloom.
|
|
6
|
+
*
|
|
7
|
+
* The velocity: in `'object'` mode with a velocity target (`P.motionBlur.w`, `@binding(5)`,
|
|
8
|
+
* `PostInputs.velocity`, uv motion since last frame) the pixel's own value, so a moving or
|
|
9
|
+
* skinned object smears under a still camera; a pixel the target holds no motion for (zero:
|
|
10
|
+
* nothing that writes velocity drew there) falls back to the camera: its depth reprojected
|
|
11
|
+
* through `P.reproj` (current clip → previous clip, the matrix TAA keeps). Without the target,
|
|
12
|
+
* and in `'camera'` mode, every pixel takes the camera's.
|
|
13
|
+
*/
|
|
14
|
+
import { mat4 } from '../core/math.js';
|
|
15
|
+
import { WGSL_POST_UNIFORMS } from './settings.js';
|
|
16
|
+
const clip = new Float32Array(3);
|
|
17
|
+
/**
|
|
18
|
+
* The screen-space velocity (uv units, +x right, +y down) of the pixel at `(u, v)` with clip
|
|
19
|
+
* depth `depth`, through `reproj` (current clip → previous clip): where the point was minus
|
|
20
|
+
* where it is. Written to `out[0..1]`; the shader's `velocity` does the same.
|
|
21
|
+
*/
|
|
22
|
+
export function motionVelocity(out, reproj, u, v, depth) {
|
|
23
|
+
const w = mat4.transformPoint(clip, reproj, u * 2 - 1, 1 - v * 2, depth);
|
|
24
|
+
if (w <= 0) {
|
|
25
|
+
out[0] = 0;
|
|
26
|
+
out[1] = 0;
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
const pu = clip[0] * 0.5 + 0.5;
|
|
30
|
+
const pv = 0.5 - clip[1] * 0.5;
|
|
31
|
+
out[0] = pu - u;
|
|
32
|
+
out[1] = pv - v;
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
export const MOTION_BLUR_WGSL = /* wgsl */ `
|
|
36
|
+
${WGSL_POST_UNIFORMS}
|
|
37
|
+
@group(0) @binding(1) var nearest: sampler;
|
|
38
|
+
@group(0) @binding(2) var linSamp: sampler;
|
|
39
|
+
@group(0) @binding(3) var depthTex: texture_depth_2d;
|
|
40
|
+
@group(0) @binding(4) var colorTex: texture_2d<f32>;
|
|
41
|
+
@group(0) @binding(5) var velocityTex: texture_2d<f32>;
|
|
42
|
+
|
|
43
|
+
fn velocity(uv: vec2f, d: f32) -> vec2f {
|
|
44
|
+
let prev = P.reproj * vec4f(uv.x * 2.0 - 1.0, 1.0 - uv.y * 2.0, d, 1.0);
|
|
45
|
+
if (prev.w <= 0.0) {
|
|
46
|
+
return vec2f(0.0);
|
|
47
|
+
}
|
|
48
|
+
let pn = prev.xy / prev.w;
|
|
49
|
+
return vec2f(pn.x * 0.5 + 0.5, 0.5 - pn.y * 0.5) - uv;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@fragment fn fs_main(in: FullscreenIn) -> @location(0) vec4f {
|
|
53
|
+
let uv = in.uv;
|
|
54
|
+
let d = textureSampleLevel(depthTex, nearest, uv, 0u);
|
|
55
|
+
var v = vec2f(0.0);
|
|
56
|
+
if (P.motionBlur.w > 0.5) {
|
|
57
|
+
// The target holds where the pixel is minus where it was; the gather is symmetric, but keep
|
|
58
|
+
// the camera path's sign (where it was minus where it is).
|
|
59
|
+
v = -textureSampleLevel(velocityTex, nearest, uv, 0.0).xy;
|
|
60
|
+
}
|
|
61
|
+
if (dot(v, v) < 1e-12) {
|
|
62
|
+
v = velocity(uv, d);
|
|
63
|
+
}
|
|
64
|
+
var vel = v * P.motionBlur.y;
|
|
65
|
+
// Cap the smear at a tenth of the screen so a teleport does not wipe the frame.
|
|
66
|
+
let len = length(vel);
|
|
67
|
+
if (len > 0.1) {
|
|
68
|
+
vel *= 0.1 / len;
|
|
69
|
+
}
|
|
70
|
+
let n = i32(P.motionBlur.z);
|
|
71
|
+
var sum = vec3f(0.0);
|
|
72
|
+
for (var i = 0; i < n; i++) {
|
|
73
|
+
let f = (f32(i) + 0.5) / f32(n) - 0.5;
|
|
74
|
+
sum += textureSampleLevel(colorTex, linSamp, uv + vel * f, 0.0).rgb;
|
|
75
|
+
}
|
|
76
|
+
return vec4f(sum / f32(n), 1.0);
|
|
77
|
+
}
|
|
78
|
+
`;
|