@driftengine/core 4.4.2 → 4.6.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.json +97 -0
- package/README.md +1 -1
- package/dist/geometry/boxCsg.d.ts +28 -0
- package/dist/geometry/boxCsg.js +139 -0
- package/dist/geometry/csg.d.ts +36 -0
- package/dist/geometry/csg.js +329 -0
- package/dist/geometry/meshBuilder.js +13 -0
- package/dist/geometry/meshConcat.js +1 -0
- package/dist/geometry/pixelFont.js +2 -0
- package/dist/geometry/solid.d.ts +61 -0
- package/dist/geometry/solid.js +152 -0
- package/dist/geometry/solidFlat.d.ts +35 -0
- package/dist/geometry/solidFlat.js +428 -0
- package/dist/geometry/solidHarness.d.ts +19 -0
- package/dist/geometry/solidHarness.js +66 -0
- package/dist/geometry/solidNormals.d.ts +17 -0
- package/dist/geometry/solidNormals.js +86 -0
- package/dist/geometry/solidRound.d.ts +41 -0
- package/dist/geometry/solidRound.js +323 -0
- package/dist/geometry/solidWriter.d.ts +16 -0
- package/dist/geometry/solidWriter.js +42 -0
- package/dist/index.d.ts +28 -3
- package/dist/index.js +20 -1
- package/dist/render/backend/api.d.ts +34 -14
- package/dist/render/backend/drawFog.d.ts +26 -0
- package/dist/render/backend/drawFog.js +30 -0
- package/dist/render/backend/materialChanges.d.ts +2 -1
- package/dist/render/backend/materialChanges.js +6 -1
- package/dist/render/backend/webgl2/glassTintPrograms.d.ts +13 -0
- package/dist/render/backend/webgl2/glassTintPrograms.js +38 -0
- package/dist/render/backend/webgl2/instanced.d.ts +24 -5
- package/dist/render/backend/webgl2/instanced.js +72 -15
- package/dist/render/backend/webgl2/renderer.d.ts +201 -16
- package/dist/render/backend/webgl2/renderer.js +596 -224
- package/dist/render/backend/webgpu/buffers.d.ts +29 -1
- package/dist/render/backend/webgpu/buffers.js +61 -4
- package/dist/render/backend/webgpu/depthPass.d.ts +1 -1
- package/dist/render/backend/webgpu/depthPass.js +7 -2
- package/dist/render/backend/webgpu/drawCommand.d.ts +5 -0
- package/dist/render/backend/webgpu/drawCommand.js +1 -0
- package/dist/render/backend/webgpu/flatPass.d.ts +6 -1
- package/dist/render/backend/webgpu/flatPass.js +57 -9
- package/dist/render/backend/webgpu/glassTintPass.d.ts +28 -0
- package/dist/render/backend/webgpu/glassTintPass.js +206 -0
- package/dist/render/backend/webgpu/gpuDrivenPass.d.ts +60 -1
- package/dist/render/backend/webgpu/gpuDrivenPass.js +305 -5
- package/dist/render/backend/webgpu/instanceCullPass.d.ts +34 -0
- package/dist/render/backend/webgpu/instanceCullPass.js +144 -0
- package/dist/render/backend/webgpu/instanced.d.ts +23 -2
- package/dist/render/backend/webgpu/instanced.js +41 -4
- package/dist/render/backend/webgpu/latePass.d.ts +30 -0
- package/dist/render/backend/webgpu/latePass.js +140 -0
- package/dist/render/backend/webgpu/lightVolumePass.js +5 -1
- package/dist/render/backend/webgpu/motionPass.d.ts +95 -0
- package/dist/render/backend/webgpu/motionPass.js +491 -0
- package/dist/render/backend/webgpu/pipelineCache.d.ts +10 -1
- package/dist/render/backend/webgpu/pipelineCache.js +11 -1
- package/dist/render/backend/webgpu/pointGlassTintPass.d.ts +32 -0
- package/dist/render/backend/webgpu/pointGlassTintPass.js +193 -0
- package/dist/render/backend/webgpu/pointShadowPass.d.ts +35 -6
- package/dist/render/backend/webgpu/pointShadowPass.js +105 -20
- package/dist/render/backend/webgpu/postPass.d.ts +3 -13
- package/dist/render/backend/webgpu/renderer.d.ts +271 -64
- package/dist/render/backend/webgpu/renderer.js +1395 -580
- package/dist/render/backend/webgpu/scatterPass.js +2 -1
- package/dist/render/backend/webgpu/sdfTextPass.js +6 -1
- package/dist/render/backend/webgpu/shaders/instanceCull.wgsl.d.ts +18 -0
- package/dist/render/backend/webgpu/shaders/instanceCull.wgsl.js +59 -0
- package/dist/render/backend/webgpu/skinPaletteRing.d.ts +4 -0
- package/dist/render/backend/webgpu/skinPaletteRing.js +4 -0
- package/dist/render/backend/webgpu/snapshotMips.d.ts +29 -0
- package/dist/render/backend/webgpu/snapshotMips.js +52 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +22 -3
- package/dist/render/backend/webgpu/surfaceTexturePass.js +78 -39
- package/dist/render/driftLight/bake.d.ts +7 -0
- package/dist/render/driftLight/bake.js +61 -56
- package/dist/render/driftLight/denseField.d.ts +46 -0
- package/dist/render/driftLight/denseField.js +109 -0
- package/dist/render/driftLight/lightField.d.ts +10 -5
- package/dist/render/driftLight/lightField.js +25 -19
- package/dist/render/driftLight/presence.d.ts +50 -0
- package/dist/render/driftLight/presence.js +43 -0
- package/dist/render/driftLight/uniforms.d.ts +3 -3
- package/dist/render/driftLight/uniforms.js +5 -6
- package/dist/render/driftLight/worldLightField.d.ts +41 -0
- package/dist/render/driftLight/worldLightField.js +66 -0
- package/dist/render/fixtureAtlas.d.ts +20 -0
- package/dist/render/fixtureAtlas.js +49 -0
- package/dist/render/glass.d.ts +45 -0
- package/dist/render/glass.js +39 -0
- package/dist/render/glassCasters.d.ts +40 -0
- package/dist/render/glassCasters.js +84 -0
- package/dist/render/glassShadow.d.ts +78 -0
- package/dist/render/glassShadow.js +125 -0
- package/dist/render/globalMediumPass.d.ts +2 -3
- package/dist/render/globalMediumPass.js +2 -8
- package/dist/render/gpudriven/lit.d.ts +12 -0
- package/dist/render/gpudriven/lit.js +23 -0
- package/dist/render/gpudriven/materialTable.d.ts +15 -5
- package/dist/render/gpudriven/materialTable.js +26 -6
- package/dist/render/gpudriven/pipeline.d.ts +1 -1
- package/dist/render/gpudriven/pipeline.js +4 -3
- package/dist/render/gpudriven/sunGlass.d.ts +35 -0
- package/dist/render/gpudriven/sunGlass.js +89 -0
- package/dist/render/instanceCull.d.ts +63 -0
- package/dist/render/instanceCull.js +160 -0
- package/dist/render/instances.d.ts +15 -0
- package/dist/render/lightBudget.d.ts +36 -35
- package/dist/render/lightBudget.js +38 -37
- package/dist/render/lightGrid.d.ts +42 -0
- package/dist/render/lightGrid.js +87 -0
- package/dist/render/mesh.d.ts +18 -24
- package/dist/render/mesh.js +51 -68
- package/dist/render/occlusion.d.ts +10 -0
- package/dist/render/occlusion.js +36 -7
- package/dist/render/pointGlassTint.d.ts +59 -0
- package/dist/render/pointGlassTint.js +198 -0
- package/dist/render/pointLightSelection.d.ts +7 -0
- package/dist/render/pointLightSelection.js +29 -4
- package/dist/render/pointShadowArray.d.ts +56 -3
- package/dist/render/pointShadowArray.js +127 -16
- package/dist/render/pointShadowMap.d.ts +23 -1
- package/dist/render/pointShadowMap.js +27 -1
- package/dist/render/rainField.d.ts +13 -0
- package/dist/render/rainField.js +27 -5
- package/dist/render/recon/changeFrames.d.ts +15 -0
- package/dist/render/recon/changeFrames.js +21 -0
- package/dist/render/recon/lateDepth.d.ts +11 -0
- package/dist/render/recon/lateDepth.js +70 -0
- package/dist/render/recon/lateRouting.d.ts +14 -0
- package/dist/render/recon/lateRouting.js +18 -0
- package/dist/render/recon/mover.d.ts +57 -0
- package/dist/render/recon/mover.js +86 -0
- package/dist/render/recon/resolve.d.ts +34 -4
- package/dist/render/recon/resolve.js +161 -20
- package/dist/render/renderQuality.d.ts +35 -0
- package/dist/render/renderQuality.js +7 -0
- package/dist/render/rendererHarness.js +16 -0
- package/dist/render/sceneTarget.d.ts +9 -1
- package/dist/render/sceneTarget.js +60 -12
- package/dist/render/shaders/depth.d.ts +16 -1
- package/dist/render/shaders/depth.js +94 -15
- package/dist/render/shaders/flat/directionalShadow.js +91 -6
- package/dist/render/shaders/flat/driftLight.d.ts +1 -1
- package/dist/render/shaders/flat/driftLight.js +32 -7
- package/dist/render/shaders/flat/glassTint.d.ts +6 -0
- package/dist/render/shaders/flat/glassTint.js +25 -0
- package/dist/render/shaders/flat/index.d.ts +13 -0
- package/dist/render/shaders/flat/index.js +9 -3
- package/dist/render/shaders/flat/lampGlass.d.ts +1 -0
- package/dist/render/shaders/flat/lampGlass.js +183 -0
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +190 -38
- package/dist/render/shaders/flat/pointShadow.d.ts +1 -1
- package/dist/render/shaders/flat/pointShadow.js +2 -0
- package/dist/render/shaders/flat/preamble.js +96 -26
- package/dist/render/shaders/flat/surfaceEffects.d.ts +29 -0
- package/dist/render/shaders/flat/surfaceEffects.js +152 -0
- package/dist/render/shaders/generated/depth.wgsl.d.ts +230 -7
- package/dist/render/shaders/generated/depth.wgsl.js +230 -7
- package/dist/render/shaders/generated/flat.wgsl.d.ts +1644 -1596
- package/dist/render/shaders/generated/flat.wgsl.js +1683 -1621
- package/dist/render/shaders/generated/globalMedium.wgsl.d.ts +3 -13
- package/dist/render/shaders/generated/globalMedium.wgsl.js +3 -13
- package/dist/render/shaders/generated/lightVolume.wgsl.d.ts +3 -13
- package/dist/render/shaders/generated/lightVolume.wgsl.js +21 -17
- package/dist/render/shaders/generated/octahedralResolve.wgsl.d.ts +29 -0
- package/dist/render/shaders/generated/octahedralResolve.wgsl.js +29 -0
- package/dist/render/shaders/generated/rush.wgsl.d.ts +21 -16
- package/dist/render/shaders/generated/rush.wgsl.js +21 -16
- package/dist/render/shaders/generated/sdfText.wgsl.d.ts +2 -2
- package/dist/render/shaders/generated/sdfText.wgsl.js +2 -2
- package/dist/render/shaders/generated/text.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/text.wgsl.js +1 -1
- package/dist/render/shaders/gi/driftLight.wgsl.d.ts +1 -1
- package/dist/render/shaders/gi/driftLight.wgsl.js +27 -4
- package/dist/render/shaders/globalMedium.js +6 -6
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.d.ts +7 -0
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.js +86 -1
- package/dist/render/shaders/gpudriven/cull.wgsl.d.ts +1 -1
- package/dist/render/shaders/gpudriven/cull.wgsl.js +11 -2
- package/dist/render/shaders/gpudriven/materialTable.wgsl.d.ts +1 -1
- package/dist/render/shaders/gpudriven/materialTable.wgsl.js +3 -1
- package/dist/render/shaders/gpudriven/shade.wgsl.js +50 -1
- package/dist/render/shaders/gpudriven/sunGlass.wgsl.d.ts +9 -0
- package/dist/render/shaders/gpudriven/sunGlass.wgsl.js +133 -0
- package/dist/render/shaders/lightVolume.js +6 -6
- package/dist/render/shaders/octahedralResolve.d.ts +8 -0
- package/dist/render/shaders/octahedralResolve.js +48 -17
- package/dist/render/shaders/recon/lateDepth.wgsl.d.ts +1 -0
- package/dist/render/shaders/recon/lateDepth.wgsl.js +69 -0
- package/dist/render/shaders/recon/motion.wgsl.d.ts +1 -1
- package/dist/render/shaders/recon/motion.wgsl.js +84 -0
- package/dist/render/shaders/recon/resolve.wgsl.d.ts +8 -7
- package/dist/render/shaders/recon/resolve.wgsl.js +161 -27
- package/dist/render/shaders/rush.js +11 -1
- package/dist/render/shaders/sdfText.d.ts +1 -1
- package/dist/render/shaders/sdfText.js +3 -2
- package/dist/render/shaders/text.d.ts +1 -1
- package/dist/render/shaders/text.js +18 -9
- package/dist/render/shadowCasters.d.ts +20 -1
- package/dist/render/shadowCasters.js +15 -1
- package/dist/render/shadowMap.d.ts +54 -5
- package/dist/render/shadowMap.js +190 -36
- package/dist/render/sunGlassTint.d.ts +25 -0
- package/dist/render/sunGlassTint.js +79 -0
- package/dist/render/surfaceEffects.d.ts +83 -0
- package/dist/render/surfaceEffects.js +75 -0
- package/dist/render/surfaceScene.d.ts +8 -0
- package/dist/render/surfaceScene.js +8 -0
- package/dist/render/surfaceTexture.d.ts +18 -2
- package/dist/render/surfaceTexture.js +68 -15
- package/dist/render/temporalAa.d.ts +25 -6
- package/dist/render/temporalAa.js +45 -15
- package/dist/render/textureSource.d.ts +30 -0
- package/dist/render/textureSource.js +53 -0
- package/dist/render/translucentQueue.d.ts +6 -0
- package/dist/render/translucentQueue.js +15 -1
- package/dist/render/vertexDefaults.js +2 -0
- package/dist/world/hlod.d.ts +104 -0
- package/dist/world/hlod.js +214 -0
- package/package.json +6 -6
- package/src/geometry/boxCsg.ts +186 -0
- package/src/geometry/csg.ts +384 -0
- package/src/geometry/meshBuilder.ts +15 -0
- package/src/geometry/meshConcat.ts +1 -0
- package/src/geometry/pixelFont.ts +2 -0
- package/src/geometry/solid.ts +189 -0
- package/src/geometry/solidFlat.ts +522 -0
- package/src/geometry/solidHarness.ts +83 -0
- package/src/geometry/solidNormals.ts +103 -0
- package/src/geometry/solidRound.ts +443 -0
- package/src/geometry/solidWriter.ts +58 -0
- package/src/index.ts +61 -1
- package/src/render/backend/api.ts +36 -11
- package/src/render/backend/drawFog.ts +31 -0
- package/src/render/backend/materialChanges.ts +9 -2
- package/src/render/backend/webgl2/glassTintPrograms.ts +58 -0
- package/src/render/backend/webgl2/instanced.ts +80 -14
- package/src/render/backend/webgl2/renderer.ts +700 -250
- package/src/render/backend/webgpu/buffers.ts +92 -5
- package/src/render/backend/webgpu/depthPass.ts +7 -2
- package/src/render/backend/webgpu/drawCommand.ts +6 -0
- package/src/render/backend/webgpu/flatPass.ts +62 -11
- package/src/render/backend/webgpu/glassTintPass.ts +245 -0
- package/src/render/backend/webgpu/gpuDrivenPass.ts +349 -5
- package/src/render/backend/webgpu/instanceCullPass.ts +165 -0
- package/src/render/backend/webgpu/instanced.ts +42 -4
- package/src/render/backend/webgpu/latePass.ts +161 -0
- package/src/render/backend/webgpu/lightVolumePass.ts +5 -1
- package/src/render/backend/webgpu/motionPass.ts +535 -0
- package/src/render/backend/webgpu/pipelineCache.ts +12 -1
- package/src/render/backend/webgpu/pointGlassTintPass.ts +233 -0
- package/src/render/backend/webgpu/pointShadowPass.ts +158 -26
- package/src/render/backend/webgpu/renderer.ts +1671 -670
- package/src/render/backend/webgpu/scatterPass.ts +2 -1
- package/src/render/backend/webgpu/sdfTextPass.ts +6 -1
- package/src/render/backend/webgpu/shaders/instanceCull.wgsl.ts +61 -0
- package/src/render/backend/webgpu/skinPaletteRing.ts +4 -0
- package/src/render/backend/webgpu/snapshotMips.ts +80 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +91 -51
- package/src/render/driftLight/bake.ts +85 -62
- package/src/render/driftLight/denseField.ts +149 -0
- package/src/render/driftLight/lightField.ts +33 -18
- package/src/render/driftLight/presence.ts +69 -0
- package/src/render/driftLight/uniforms.ts +8 -9
- package/src/render/driftLight/worldLightField.ts +83 -0
- package/src/render/fixtureAtlas.ts +63 -0
- package/src/render/glass.ts +74 -0
- package/src/render/glassCasters.ts +164 -0
- package/src/render/glassShadow.ts +153 -0
- package/src/render/globalMediumPass.ts +4 -11
- package/src/render/gpudriven/lit.ts +31 -0
- package/src/render/gpudriven/materialTable.ts +28 -6
- package/src/render/gpudriven/pipeline.ts +4 -3
- package/src/render/gpudriven/sunGlass.ts +117 -0
- package/src/render/instanceCull.ts +205 -0
- package/src/render/instances.ts +16 -0
- package/src/render/lightBudget.ts +41 -38
- package/src/render/lightGrid.ts +130 -0
- package/src/render/mesh.ts +59 -72
- package/src/render/occlusion.ts +51 -7
- package/src/render/pointGlassTint.ts +250 -0
- package/src/render/pointLightSelection.ts +72 -4
- package/src/render/pointShadowArray.ts +188 -22
- package/src/render/pointShadowMap.ts +41 -0
- package/src/render/rainField.ts +39 -5
- package/src/render/recon/changeFrames.ts +24 -0
- package/src/render/recon/lateDepth.ts +83 -0
- package/src/render/recon/lateRouting.ts +29 -0
- package/src/render/recon/mover.ts +118 -0
- package/src/render/recon/resolve.ts +206 -20
- package/src/render/renderQuality.ts +47 -0
- package/src/render/rendererHarness.ts +16 -0
- package/src/render/sceneTarget.ts +62 -11
- package/src/render/shaders/depth.ts +118 -15
- package/src/render/shaders/flat/directionalShadow.ts +97 -6
- package/src/render/shaders/flat/driftLight.ts +32 -7
- package/src/render/shaders/flat/glassTint.ts +25 -0
- package/src/render/shaders/flat/index.ts +22 -3
- package/src/render/shaders/flat/lampGlass.ts +185 -0
- package/src/render/shaders/flat/main.ts +190 -38
- package/src/render/shaders/flat/pointShadow.ts +2 -0
- package/src/render/shaders/flat/preamble.ts +96 -26
- package/src/render/shaders/flat/surfaceEffects.ts +152 -0
- package/src/render/shaders/generated/depth.wgsl.ts +237 -7
- package/src/render/shaders/generated/flat.wgsl.ts +1685 -1621
- package/src/render/shaders/generated/globalMedium.wgsl.ts +3 -13
- package/src/render/shaders/generated/lightVolume.wgsl.ts +23 -17
- package/src/render/shaders/generated/octahedralResolve.wgsl.ts +30 -0
- package/src/render/shaders/generated/rush.wgsl.ts +21 -16
- package/src/render/shaders/generated/sdfText.wgsl.ts +2 -2
- package/src/render/shaders/generated/text.wgsl.ts +1 -1
- package/src/render/shaders/gi/driftLight.wgsl.ts +27 -4
- package/src/render/shaders/globalMedium.ts +6 -6
- package/src/render/shaders/gpudriven/blendRaster.wgsl.ts +88 -1
- package/src/render/shaders/gpudriven/cull.wgsl.ts +11 -2
- package/src/render/shaders/gpudriven/materialTable.wgsl.ts +3 -1
- package/src/render/shaders/gpudriven/shade.wgsl.ts +50 -1
- package/src/render/shaders/gpudriven/sunGlass.wgsl.ts +139 -0
- package/src/render/shaders/lightVolume.ts +6 -6
- package/src/render/shaders/octahedralResolve.ts +50 -17
- package/src/render/shaders/recon/lateDepth.wgsl.ts +72 -0
- package/src/render/shaders/recon/motion.wgsl.ts +84 -0
- package/src/render/shaders/recon/resolve.wgsl.ts +161 -27
- package/src/render/shaders/rush.ts +11 -1
- package/src/render/shaders/sdfText.ts +3 -2
- package/src/render/shaders/text.ts +18 -9
- package/src/render/shadowCasters.ts +28 -1
- package/src/render/shadowMap.ts +231 -37
- package/src/render/sunGlassTint.ts +86 -0
- package/src/render/surfaceEffects.ts +132 -0
- package/src/render/surfaceScene.ts +16 -0
- package/src/render/surfaceTexture.ts +110 -19
- package/src/render/temporalAa.ts +78 -14
- package/src/render/textureSource.ts +72 -0
- package/src/render/translucentQueue.ts +20 -1
- package/src/render/vertexDefaults.ts +2 -0
- package/src/world/hlod.ts +290 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The render's depth, taken up to the output size for the draws that land after the upscale.
|
|
3
|
+
*
|
|
4
|
+
* `recon/lateDepth.ts` is the same arithmetic and says why: **each of the four render texels about
|
|
5
|
+
* the pixel carries its surface on to the pixel's unjittered centre** along a slope the minmod
|
|
6
|
+
* limiter takes — the smaller of its two differences on an axis, none where they disagree — and the
|
|
7
|
+
* nearest of the four so carried stands, less a quarter of its slope. On a plane that is the plane's
|
|
8
|
+
* own depth at the pixel whatever the jitter; at an edge no slope crosses the jump, so a
|
|
9
|
+
* translucent draw is never let through an opaque edge the render covered.
|
|
10
|
+
*
|
|
11
|
+
* Hand-written, and built by concatenation rather than a template literal: the reconstruction's
|
|
12
|
+
* passes have no WebGL2 twin (the AGENTS.md exception for them), and a `${}` inside WGSL source is
|
|
13
|
+
* the thing that rule forbids.
|
|
14
|
+
*/
|
|
15
|
+
import { REVERSED_DEPTH } from '../../depthConvention.ts';
|
|
16
|
+
|
|
17
|
+
/** The nearer of two stored depths: the larger in a reversed buffer. */
|
|
18
|
+
const NEARER = REVERSED_DEPTH ? 'max' : 'min';
|
|
19
|
+
/** Toward the far side: down in a reversed buffer. */
|
|
20
|
+
const FARWARD = REVERSED_DEPTH ? '-' : '+';
|
|
21
|
+
/** Where the search for the nearest starts: the far plane. */
|
|
22
|
+
const FARTHEST = REVERSED_DEPTH ? '0.0' : '1.0';
|
|
23
|
+
|
|
24
|
+
export const LATE_DEPTH_WGSL =
|
|
25
|
+
'@group(0) @binding(0) var source: texture_depth_2d;\n' +
|
|
26
|
+
'/* The render size and the output size; then the frame jitter, in render texels. */\n' +
|
|
27
|
+
'@group(0) @binding(1) var<uniform> sizes: array<vec4<f32>, 2>;\n' +
|
|
28
|
+
'\n' +
|
|
29
|
+
'@vertex\n' +
|
|
30
|
+
'fn lateDepthVert(@builtin(vertex_index) index: u32) -> @builtin(position) vec4<f32> {\n' +
|
|
31
|
+
' let x = f32((index << 1u) & 2u);\n' +
|
|
32
|
+
' let y = f32(index & 2u);\n' +
|
|
33
|
+
' return vec4<f32>(x * 2.0 - 1.0, 1.0 - y * 2.0, 0.0, 1.0);\n' +
|
|
34
|
+
'}\n' +
|
|
35
|
+
'\n' +
|
|
36
|
+
'fn tap(base: vec2<i32>, x: i32, y: i32) -> f32 {\n' +
|
|
37
|
+
' let top = vec2<i32>(sizes[0].xy) - vec2<i32>(1);\n' +
|
|
38
|
+
' return textureLoad(source, clamp(base + vec2<i32>(x, y), vec2<i32>(0), top), 0);\n' +
|
|
39
|
+
'}\n' +
|
|
40
|
+
'\n' +
|
|
41
|
+
'/* The smaller of two differences, or none where they disagree in sign. */\n' +
|
|
42
|
+
'fn minmod(a: f32, b: f32) -> f32 {\n' +
|
|
43
|
+
' if (a * b <= 0.0) {\n' +
|
|
44
|
+
' return 0.0;\n' +
|
|
45
|
+
' }\n' +
|
|
46
|
+
' return select(b, a, abs(a) < abs(b));\n' +
|
|
47
|
+
'}\n' +
|
|
48
|
+
'\n' +
|
|
49
|
+
'@fragment\n' +
|
|
50
|
+
'fn lateDepthFrag(@builtin(position) at: vec4<f32>) -> @builtin(frag_depth) f32 {\n' +
|
|
51
|
+
' /* A texel stands at its index plus a half less the jitter, as the resolve places it. */\n' +
|
|
52
|
+
' let centre = at.xy * sizes[0].xy / sizes[0].zw - vec2<f32>(0.5) + sizes[1].xy;\n' +
|
|
53
|
+
' let base = vec2<i32>(floor(centre));\n' +
|
|
54
|
+
' let f = centre - floor(centre);\n' +
|
|
55
|
+
' var depth = ' +
|
|
56
|
+
FARTHEST +
|
|
57
|
+
';\n' +
|
|
58
|
+
' for (var oy = 0; oy < 2; oy += 1) {\n' +
|
|
59
|
+
' for (var ox = 0; ox < 2; ox += 1) {\n' +
|
|
60
|
+
' let d = tap(base, ox, oy);\n' +
|
|
61
|
+
' let gx = minmod(tap(base, ox + 1, oy) - d, d - tap(base, ox - 1, oy));\n' +
|
|
62
|
+
' let gy = minmod(tap(base, ox, oy + 1) - d, d - tap(base, ox, oy - 1));\n' +
|
|
63
|
+
' let carried = d + gx * (f.x - f32(ox)) + gy * (f.y - f32(oy));\n' +
|
|
64
|
+
' depth = ' +
|
|
65
|
+
NEARER +
|
|
66
|
+
'(depth, carried ' +
|
|
67
|
+
FARWARD +
|
|
68
|
+
' 0.25 * max(abs(gx), abs(gy)));\n' +
|
|
69
|
+
' }\n' +
|
|
70
|
+
' }\n' +
|
|
71
|
+
' return clamp(depth, 0.0, 1.0);\n' +
|
|
72
|
+
'}\n';
|
|
@@ -88,6 +88,90 @@ fn motionUv(clip: vec4<f32>) -> vec2<f32> {
|
|
|
88
88
|
return clip.xy / clip.w * 0.5 + vec2<f32>(0.5);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
/*
|
|
92
|
+
* The skinned stage: the joints this frame and last frame, read from two palette textures of the
|
|
93
|
+
* frame's ring. The same four weighted products in the same order as the scene's own skinning, so
|
|
94
|
+
* the depth this stage produces is the depth the scene wrote.
|
|
95
|
+
*/
|
|
96
|
+
@group(1) @binding(0) var palette: texture_2d<f32>;
|
|
97
|
+
@group(1) @binding(1) var previousPalette: texture_2d<f32>;
|
|
98
|
+
|
|
99
|
+
fn jointOf(source: texture_2d<f32>, index: i32) -> mat4x4<f32> {
|
|
100
|
+
let x = index * 4;
|
|
101
|
+
return mat4x4<f32>(
|
|
102
|
+
textureLoad(source, vec2<i32>(x, 0), 0),
|
|
103
|
+
textureLoad(source, vec2<i32>(x + 1, 0), 0),
|
|
104
|
+
textureLoad(source, vec2<i32>(x + 2, 0), 0),
|
|
105
|
+
textureLoad(source, vec2<i32>(x + 3, 0), 0));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
fn skinOf(source: texture_2d<f32>, joints: vec4<f32>, weights: vec4<f32>) -> mat4x4<f32> {
|
|
109
|
+
return jointOf(source, i32(joints.x)) * weights.x
|
|
110
|
+
+ jointOf(source, i32(joints.y)) * weights.y
|
|
111
|
+
+ jointOf(source, i32(joints.z)) * weights.z
|
|
112
|
+
+ jointOf(source, i32(joints.w)) * weights.w;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@vertex
|
|
116
|
+
fn motionSkinnedVert(
|
|
117
|
+
@location(0) position: vec3<f32>,
|
|
118
|
+
@location(11) joints: vec4<f32>,
|
|
119
|
+
@location(12) weights: vec4<f32>,
|
|
120
|
+
) -> Varyings {
|
|
121
|
+
let world = draw.model * (skinOf(palette, joints, weights) * vec4<f32>(position, 1.0));
|
|
122
|
+
let wasWorld =
|
|
123
|
+
draw.previousModel * (skinOf(previousPalette, joints, weights) * vec4<f32>(position, 1.0));
|
|
124
|
+
var out: Varyings;
|
|
125
|
+
out.clip = frame.raster * world;
|
|
126
|
+
out.now = frame.viewProj * world;
|
|
127
|
+
out.was = frame.previousViewProj * wasWorld;
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/*
|
|
132
|
+
* The rewritten stage: a mesh whose vertices were rewritten this frame reads last frame's rows from
|
|
133
|
+
* a second buffer of the same stride, so each vertex carries both of its positions.
|
|
134
|
+
*/
|
|
135
|
+
@vertex
|
|
136
|
+
fn motionDynamicVert(
|
|
137
|
+
@location(0) position: vec3<f32>,
|
|
138
|
+
@location(1) previousPosition: vec3<f32>,
|
|
139
|
+
) -> Varyings {
|
|
140
|
+
let world = draw.model * vec4<f32>(position, 1.0);
|
|
141
|
+
let wasWorld = draw.previousModel * vec4<f32>(previousPosition, 1.0);
|
|
142
|
+
var out: Varyings;
|
|
143
|
+
out.clip = frame.raster * world;
|
|
144
|
+
out.now = frame.viewProj * world;
|
|
145
|
+
out.was = frame.previousViewProj * wasWorld;
|
|
146
|
+
return out;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/*
|
|
150
|
+
* The instanced stage: each instance's matrix this frame and last frame, read from the batch's
|
|
151
|
+
* placement and the copy of last frame's it kept. Slot for slot, so an instance is paired with
|
|
152
|
+
* itself; the per-draw matrices are not read.
|
|
153
|
+
*/
|
|
154
|
+
@vertex
|
|
155
|
+
fn motionInstancedVert(
|
|
156
|
+
@location(0) position: vec3<f32>,
|
|
157
|
+
@location(2) m0: vec4<f32>,
|
|
158
|
+
@location(3) m1: vec4<f32>,
|
|
159
|
+
@location(4) m2: vec4<f32>,
|
|
160
|
+
@location(5) m3: vec4<f32>,
|
|
161
|
+
@location(6) p0: vec4<f32>,
|
|
162
|
+
@location(7) p1: vec4<f32>,
|
|
163
|
+
@location(8) p2: vec4<f32>,
|
|
164
|
+
@location(9) p3: vec4<f32>,
|
|
165
|
+
) -> Varyings {
|
|
166
|
+
let world = mat4x4<f32>(m0, m1, m2, m3) * vec4<f32>(position, 1.0);
|
|
167
|
+
let wasWorld = mat4x4<f32>(p0, p1, p2, p3) * vec4<f32>(position, 1.0);
|
|
168
|
+
var out: Varyings;
|
|
169
|
+
out.clip = frame.raster * world;
|
|
170
|
+
out.now = frame.viewProj * world;
|
|
171
|
+
out.was = frame.previousViewProj * wasWorld;
|
|
172
|
+
return out;
|
|
173
|
+
}
|
|
174
|
+
|
|
91
175
|
@fragment
|
|
92
176
|
fn motionFrag(in: Varyings) -> @location(0) vec4<f32> {
|
|
93
177
|
/*
|
|
@@ -34,12 +34,16 @@
|
|
|
34
34
|
* fn reconMotion(x: i32, y: i32) -> vec4<f32> // uv, previous view depth, flag
|
|
35
35
|
* fn reconHistory(x: i32, y: i32) -> vec4<f32> // output size, colour and gathered weight
|
|
36
36
|
* fn reconHistoryBilinear(p: vec2<f32>) -> vec4<f32>
|
|
37
|
+
* fn reconFlicker(x: i32, y: i32) -> vec4<f32> // output size, last frame's flicker record
|
|
38
|
+
* fn reconSwing(x: i32, y: i32) -> f32 // output size, last frame's held depth swing
|
|
37
39
|
* ```
|
|
38
40
|
*
|
|
39
41
|
* and the uniform `recon: ReconParams`, whose struct this module declares.
|
|
40
42
|
*/
|
|
41
43
|
import { wgslSceneDepthToNdc } from '../../depthConvention.ts';
|
|
42
44
|
import { PLANAR_FROM, PLANAR_TO } from '../../recon/disocclusion.ts';
|
|
45
|
+
import { DEPTH_SWING_WIDTH } from '../../recon/resolve.ts';
|
|
46
|
+
import { FLICKER_BLEND, FLICKER_REPEAT, STILL_FROM, STILL_TO } from '../../temporalAa.ts';
|
|
43
47
|
|
|
44
48
|
/**
|
|
45
49
|
* The parameters one resolve reads, as `ResolveFrame` minus its images.
|
|
@@ -66,11 +70,16 @@ struct ReconParams {
|
|
|
66
70
|
motionScale: f32,
|
|
67
71
|
normalFloor: f32,
|
|
68
72
|
normalCeiling: f32,
|
|
73
|
+
periodStart: u32,
|
|
74
|
+
antiFlicker: u32,
|
|
75
|
+
flickerMemory: f32,
|
|
76
|
+
flickerWidth: f32,
|
|
77
|
+
reprojection: mat4x4<f32>,
|
|
69
78
|
}
|
|
70
79
|
`;
|
|
71
80
|
|
|
72
81
|
/** Floats in `ReconParams`, which is what a caller sizes its uniform buffer by. */
|
|
73
|
-
export const RECON_PARAM_FLOATS =
|
|
82
|
+
export const RECON_PARAM_FLOATS = 92;
|
|
74
83
|
|
|
75
84
|
/** `SAMPLE_SPREAD` and `CONFIDENT_WEIGHT`, which the reference exports and this must not restate. */
|
|
76
85
|
export const RECON_SAMPLE_SPREAD = 0.47;
|
|
@@ -91,8 +100,8 @@ export const RECON_WORKGROUP = 8;
|
|
|
91
100
|
export const RECON_HISTORY_FORMAT: GPUTextureFormat = 'rgba16float';
|
|
92
101
|
|
|
93
102
|
/**
|
|
94
|
-
* The arithmetic, as text. Defines `reconResolvePixel(ox, oy) ->
|
|
95
|
-
* colour and the weight it has gathered — and `reconSharpenAt(ox, oy) -> vec3<f32>`, the picture
|
|
103
|
+
* The arithmetic, as text. Defines `reconResolvePixel(ox, oy) -> ReconResolved` — the next
|
|
104
|
+
* history's colour and the weight it has gathered, and the pixel's next flicker record — and `reconSharpenAt(ox, oy) -> vec3<f32>`, the picture
|
|
96
105
|
* shown, which reads the history the first has already written.
|
|
97
106
|
*/
|
|
98
107
|
export const RECON_RESOLVE_CORE_WGSL = /* wgsl */ `
|
|
@@ -100,6 +109,11 @@ const RECON_SAMPLE_SPREAD: f32 = ${RECON_SAMPLE_SPREAD};
|
|
|
100
109
|
const RECON_CONFIDENT_WEIGHT: f32 = ${RECON_CONFIDENT_WEIGHT}.0;
|
|
101
110
|
const RECON_PLANAR_FROM: f32 = ${PLANAR_FROM};
|
|
102
111
|
const RECON_PLANAR_TO: f32 = ${PLANAR_TO};
|
|
112
|
+
const RECON_FLICKER_BLEND: f32 = ${FLICKER_BLEND};
|
|
113
|
+
const RECON_FLICKER_REPEAT: f32 = ${FLICKER_REPEAT};
|
|
114
|
+
const RECON_STILL_FROM: f32 = ${STILL_FROM};
|
|
115
|
+
const RECON_STILL_TO: f32 = ${STILL_TO};
|
|
116
|
+
const RECON_DEPTH_SWING_WIDTH: f32 = ${DEPTH_SWING_WIDTH}.0;
|
|
103
117
|
|
|
104
118
|
fn reconClampTexel(value: i32, size: i32) -> i32 {
|
|
105
119
|
return clamp(value, 0, size - 1);
|
|
@@ -467,6 +481,10 @@ fn reconSurfaceAt(previous: bool, x: i32, y: i32, centre: f32) -> ReconSurface {
|
|
|
467
481
|
struct ReconHistory {
|
|
468
482
|
weight: f32,
|
|
469
483
|
colour: vec4<f32>,
|
|
484
|
+
/* How far the surface moved, in output pixels; read only where the weight is not zero. */
|
|
485
|
+
moved: f32,
|
|
486
|
+
/* How far, relative, last frame's depth missed the one expected there; -1 where none was held. */
|
|
487
|
+
missed: f32,
|
|
470
488
|
}
|
|
471
489
|
|
|
472
490
|
/*
|
|
@@ -474,10 +492,12 @@ struct ReconHistory {
|
|
|
474
492
|
* behind last frame's eye or off its picture, and otherwise what it gathered, scaled by whether it
|
|
475
493
|
* is the same surface.
|
|
476
494
|
*/
|
|
477
|
-
fn reconHistoryWeight(u: f32, v: f32, dx: i32, dy: i32) -> ReconHistory {
|
|
495
|
+
fn reconHistoryWeight(u: f32, v: f32, dx: i32, dy: i32, swing: f32) -> ReconHistory {
|
|
478
496
|
var out: ReconHistory;
|
|
479
497
|
out.weight = 0.0;
|
|
480
498
|
out.colour = vec4<f32>(0.0);
|
|
499
|
+
out.moved = 0.0;
|
|
500
|
+
out.missed = -1.0;
|
|
481
501
|
if (recon.hasHistory == 0u) { return out; }
|
|
482
502
|
let rw = f32(recon.renderSize.x);
|
|
483
503
|
let rh = f32(recon.renderSize.y);
|
|
@@ -490,20 +510,24 @@ fn reconHistoryWeight(u: f32, v: f32, dx: i32, dy: i32) -> ReconHistory {
|
|
|
490
510
|
mv = motion.y;
|
|
491
511
|
expected = motion.z;
|
|
492
512
|
} else {
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
let
|
|
513
|
+
/* Through the one reprojection matrix the renderer multiplied: see resolve.ts. */
|
|
514
|
+
let du = (f32(dx) + 0.5 - recon.jitter.x) / rw;
|
|
515
|
+
let dv = (f32(dy) + 0.5 - recon.jitter.y) / rh;
|
|
516
|
+
let ndc = vec4<f32>(du * 2.0 - 1.0, dv * 2.0 - 1.0, reconDepth(dx, dy), 1.0);
|
|
517
|
+
let m = recon.inverseViewProj;
|
|
518
|
+
let hw = m[0][3] * ndc.x + m[1][3] * ndc.y + m[2][3] * ndc.z + m[3][3];
|
|
519
|
+
if (!(hw > 1e-12)) { return out; }
|
|
520
|
+
let clip = recon.reprojection * ndc;
|
|
496
521
|
/*
|
|
497
522
|
* A surface behind last frame's eye has a w that is not positive: the disocclusion trusts no
|
|
498
523
|
* such depth, so it needs no refusal of its own here.
|
|
499
524
|
*/
|
|
500
|
-
expected = clip.w;
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
mu = (clip.x / expected) * 0.5 + 0.5 - du;
|
|
504
|
-
mv = (clip.y / expected) * 0.5 + 0.5 - dv;
|
|
525
|
+
expected = clip.w / hw;
|
|
526
|
+
mu = (clip.x / clip.w) * 0.5 + 0.5 - du;
|
|
527
|
+
mv = (clip.y / clip.w) * 0.5 + 0.5 - dv;
|
|
505
528
|
}
|
|
506
529
|
|
|
530
|
+
out.moved = length(vec2<f32>(mu * f32(recon.outputSize.x), mv * f32(recon.outputSize.y)));
|
|
507
531
|
let pu = u + mu;
|
|
508
532
|
let pv = v + mv;
|
|
509
533
|
if (!(pu >= 0.0 && pu <= 1.0 && pv >= 0.0 && pv <= 1.0)) { return out; }
|
|
@@ -550,13 +574,41 @@ fn reconHistoryWeight(u: f32, v: f32, dx: i32, dy: i32) -> ReconHistory {
|
|
|
550
574
|
normalDot = 1.0 - planar * (1.0 - dot(hereNormal.normal, thereNormal.normal));
|
|
551
575
|
}
|
|
552
576
|
}
|
|
553
|
-
|
|
577
|
+
if (held > 0.0 && expected > 0.0) { out.missed = abs(held - expected) / expected; }
|
|
578
|
+
/* A still pixel's own held depth swing: see resolve.ts. */
|
|
579
|
+
var swung = 0.0;
|
|
580
|
+
if (swing > 0.0) {
|
|
581
|
+
swung = RECON_DEPTH_SWING_WIDTH * swing *
|
|
582
|
+
(1.0 - reconSmoothstep(RECON_STILL_FROM, RECON_STILL_TO, out.moved));
|
|
583
|
+
}
|
|
584
|
+
let trust = reconDisocclusion(
|
|
585
|
+
expected,
|
|
586
|
+
held,
|
|
587
|
+
length(vec2<f32>(mu, mv)),
|
|
588
|
+
normalDot,
|
|
589
|
+
here.slope + swung,
|
|
590
|
+
);
|
|
554
591
|
out.weight = out.colour.w * trust;
|
|
555
592
|
return out;
|
|
556
593
|
}
|
|
557
594
|
|
|
558
|
-
/*
|
|
559
|
-
fn
|
|
595
|
+
/* temporalAa.ts's repeats: whether two periods' means are the same, one to zero. */
|
|
596
|
+
fn reconRepeats(mean: f32, previous: f32) -> f32 {
|
|
597
|
+
let apart = abs(mean - previous) / max(max(mean, previous), 1.0 / 255.0);
|
|
598
|
+
return 1.0 - reconSmoothstep(RECON_FLICKER_REPEAT, 2.0 * RECON_FLICKER_REPEAT, apart);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
struct ReconResolved {
|
|
602
|
+
/* The history's next colour, before sharpening, and the weight it has gathered. */
|
|
603
|
+
colour: vec4<f32>,
|
|
604
|
+
/* The pixel's next flicker record: spread, this period's sum, last period's mean, repeats. */
|
|
605
|
+
record: vec4<f32>,
|
|
606
|
+
/* And its next held depth swing. */
|
|
607
|
+
swing: f32,
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/* One output pixel: the history's next colour and weight, and its next flicker record. */
|
|
611
|
+
fn reconResolvePixel(ox: i32, oy: i32) -> ReconResolved {
|
|
560
612
|
let rw = i32(recon.renderSize.x);
|
|
561
613
|
let rh = i32(recon.renderSize.y);
|
|
562
614
|
let ow = i32(recon.outputSize.x);
|
|
@@ -604,18 +656,68 @@ fn reconResolvePixel(ox: i32, oy: i32) -> vec4<f32> {
|
|
|
604
656
|
accum = accum / gathered;
|
|
605
657
|
|
|
606
658
|
/* The history, and the weight it still deserves; a tenth of each frame is always new. */
|
|
607
|
-
|
|
608
|
-
|
|
659
|
+
var swing = 0.0;
|
|
660
|
+
if (recon.antiFlicker != 0u) { swing = reconSwing(ox, oy); }
|
|
661
|
+
let history = reconHistoryWeight(u, v, dx, dy, swing);
|
|
662
|
+
var cap = (1.0 - recon.alpha) / recon.alpha;
|
|
663
|
+
var low = box.low;
|
|
664
|
+
var high = box.high;
|
|
665
|
+
var out: ReconResolved;
|
|
666
|
+
out.record = vec4<f32>(0.0);
|
|
667
|
+
out.swing = 0.0;
|
|
668
|
+
/* The anti-flicker, operation for operation resolve.ts's: see temporalAa.ts. */
|
|
669
|
+
if (recon.antiFlicker != 0u) {
|
|
670
|
+
let seen = dot(accum, vec3<f32>(0.2126, 0.7152, 0.0722));
|
|
671
|
+
let memory = recon.flickerMemory;
|
|
672
|
+
let width = recon.flickerWidth;
|
|
673
|
+
var held = vec4<f32>(0.0, seen * memory, seen, 0.0);
|
|
674
|
+
if (history.weight > 0.0) { held = reconFlicker(ox, oy); }
|
|
675
|
+
var still = 0.0;
|
|
676
|
+
if (history.weight > 0.0) {
|
|
677
|
+
still = 1.0 - reconSmoothstep(RECON_STILL_FROM, RECON_STILL_TO, history.moved);
|
|
678
|
+
}
|
|
679
|
+
let apart = abs(seen - held.z);
|
|
680
|
+
let within = apart <= width * held.x + 1.0 / 255.0;
|
|
681
|
+
let proven = held.w > 0.75 && within;
|
|
682
|
+
var widen = 0.0;
|
|
683
|
+
let base = 1.0 - recon.alpha;
|
|
684
|
+
var keep = base;
|
|
685
|
+
if (proven) {
|
|
686
|
+
widen = width * held.x * still;
|
|
687
|
+
keep = base + (RECON_FLICKER_BLEND - base) * still;
|
|
688
|
+
}
|
|
689
|
+
low = low - vec3<f32>(widen);
|
|
690
|
+
high = high + vec3<f32>(widen);
|
|
691
|
+
cap = keep / (1.0 - keep);
|
|
692
|
+
var sum = held.y;
|
|
693
|
+
var mean = held.z;
|
|
694
|
+
var repeated = 0.0;
|
|
695
|
+
if (within) { repeated = held.w; }
|
|
696
|
+
if (recon.periodStart != 0u) {
|
|
697
|
+
if (reconRepeats(sum, mean) > 0.5) { repeated = min(1.0, repeated + 0.5); } else { repeated = 0.0; }
|
|
698
|
+
mean = sum;
|
|
699
|
+
sum = 0.0;
|
|
700
|
+
}
|
|
701
|
+
out.record = vec4<f32>(
|
|
702
|
+
held.x + (apart - held.x) * memory,
|
|
703
|
+
sum + seen * memory,
|
|
704
|
+
mean,
|
|
705
|
+
repeated * still,
|
|
706
|
+
);
|
|
707
|
+
/* The peak carried on, halving over a period, whatever the test said. */
|
|
708
|
+
if (history.missed >= 0.0) { out.swing = max(history.missed, swing * pow(0.5, memory)); }
|
|
709
|
+
}
|
|
609
710
|
let kept = min(cap, history.weight);
|
|
610
711
|
|
|
611
712
|
let total = kept + gathered;
|
|
612
713
|
var mixed = accum;
|
|
613
714
|
if (kept > 0.0) {
|
|
614
|
-
let clipped = reconClipToBox(reconToYCoCg(history.colour.xyz),
|
|
715
|
+
let clipped = reconClipToBox(reconToYCoCg(history.colour.xyz), low, high);
|
|
615
716
|
mixed = reconAccumulate(accum, reconFromYCoCg(clipped), 1.0, gathered / total);
|
|
616
717
|
}
|
|
617
718
|
let known = min(1.0, total / RECON_CONFIDENT_WEIGHT);
|
|
618
|
-
|
|
719
|
+
out.colour = vec4<f32>(sample * (1.0 - known) + mixed * known, total);
|
|
720
|
+
return out;
|
|
619
721
|
}
|
|
620
722
|
|
|
621
723
|
/*
|
|
@@ -655,8 +757,9 @@ fn reconSharpenAt(ox: i32, oy: i32) -> vec3<f32> {
|
|
|
655
757
|
* doing its own bilinear so the comparison is arithmetic rather than a tolerance on the device's
|
|
656
758
|
* sampler.
|
|
657
759
|
*
|
|
658
|
-
* Two entry points over one set of bindings. `resolveMain` writes
|
|
659
|
-
* history — and `sharpenMain` reads that history back at binding 4
|
|
760
|
+
* Two entry points over one set of bindings. `resolveMain` writes nine floats a pixel — the next
|
|
761
|
+
* history, the next flicker record and the next depth swing — and `sharpenMain` reads that history back at binding 4
|
|
762
|
+
* and writes three.
|
|
660
763
|
*/
|
|
661
764
|
export function reconResolveParityWgsl(): string {
|
|
662
765
|
return /* wgsl */ `
|
|
@@ -668,6 +771,16 @@ export function reconResolveParityWgsl(): string {
|
|
|
668
771
|
${RECON_PARAMS_WGSL}
|
|
669
772
|
@group(0) @binding(5) var<uniform> recon: ReconParams;
|
|
670
773
|
@group(0) @binding(6) var<storage, read_write> output: array<f32>;
|
|
774
|
+
@group(0) @binding(7) var flickerTexture: texture_2d<f32>;
|
|
775
|
+
@group(0) @binding(8) var swingTexture: texture_2d<f32>;
|
|
776
|
+
|
|
777
|
+
fn reconFlicker(x: i32, y: i32) -> vec4<f32> {
|
|
778
|
+
return textureLoad(flickerTexture, vec2<i32>(x, y), 0);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
fn reconSwing(x: i32, y: i32) -> f32 {
|
|
782
|
+
return textureLoad(swingTexture, vec2<i32>(x, y), 0).x;
|
|
783
|
+
}
|
|
671
784
|
|
|
672
785
|
fn reconScene(x: i32, y: i32) -> vec3<f32> {
|
|
673
786
|
return textureLoad(sceneTexture, vec2<i32>(x, y), 0).xyz;
|
|
@@ -725,11 +838,16 @@ ${RECON_RESOLVE_CORE_WGSL}
|
|
|
725
838
|
fn resolveMain(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
726
839
|
if (id.x >= recon.outputSize.x || id.y >= recon.outputSize.y) { return; }
|
|
727
840
|
let value = reconResolvePixel(i32(id.x), i32(id.y));
|
|
728
|
-
let at = (id.y * recon.outputSize.x + id.x) *
|
|
729
|
-
output[at] = value.x;
|
|
730
|
-
output[at + 1u] = value.y;
|
|
731
|
-
output[at + 2u] = value.z;
|
|
732
|
-
output[at + 3u] = value.w;
|
|
841
|
+
let at = (id.y * recon.outputSize.x + id.x) * 9u;
|
|
842
|
+
output[at] = value.colour.x;
|
|
843
|
+
output[at + 1u] = value.colour.y;
|
|
844
|
+
output[at + 2u] = value.colour.z;
|
|
845
|
+
output[at + 3u] = value.colour.w;
|
|
846
|
+
output[at + 4u] = value.record.x;
|
|
847
|
+
output[at + 5u] = value.record.y;
|
|
848
|
+
output[at + 6u] = value.record.z;
|
|
849
|
+
output[at + 7u] = value.record.w;
|
|
850
|
+
output[at + 8u] = value.swing;
|
|
733
851
|
}
|
|
734
852
|
|
|
735
853
|
@compute @workgroup_size(${RECON_WORKGROUP}, ${RECON_WORKGROUP})
|
|
@@ -780,6 +898,12 @@ ${RECON_PARAMS_WGSL}
|
|
|
780
898
|
@group(0) @binding(6) var<uniform> recon: ReconParams;
|
|
781
899
|
@group(0) @binding(7) var resolved: texture_storage_2d<rgba16float, write>;
|
|
782
900
|
/* Not "target": it is a reserved keyword in WGSL, as "meta" was in the cluster cull. */
|
|
901
|
+
/* Last frame's flicker records, and where this frame's go: a pair beside the histories. */
|
|
902
|
+
@group(0) @binding(8) var flickerTexture: texture_2d<f32>;
|
|
903
|
+
@group(0) @binding(9) var flickerOut: texture_storage_2d<rgba16float, write>;
|
|
904
|
+
/* And each pixel's held depth swing, a pair of its own. */
|
|
905
|
+
@group(0) @binding(10) var swingTexture: texture_2d<f32>;
|
|
906
|
+
@group(0) @binding(11) var swingOut: texture_storage_2d<r32float, write>;
|
|
783
907
|
|
|
784
908
|
/* Rows flip here: the reference's row 0 is the bottom one and a texture's is the top. */
|
|
785
909
|
fn reconRenderRow(y: i32) -> i32 {
|
|
@@ -812,6 +936,14 @@ fn reconHistory(x: i32, y: i32) -> vec4<f32> {
|
|
|
812
936
|
return textureLoad(historyTexture, vec2<i32>(x, reconOutputRow(y)), 0);
|
|
813
937
|
}
|
|
814
938
|
|
|
939
|
+
fn reconFlicker(x: i32, y: i32) -> vec4<f32> {
|
|
940
|
+
return textureLoad(flickerTexture, vec2<i32>(x, reconOutputRow(y)), 0);
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
fn reconSwing(x: i32, y: i32) -> f32 {
|
|
944
|
+
return textureLoad(swingTexture, vec2<i32>(x, reconOutputRow(y)), 0).x;
|
|
945
|
+
}
|
|
946
|
+
|
|
815
947
|
/* A texel coordinate becomes the uv of its centre, with the row taken from the other end. */
|
|
816
948
|
fn reconSceneBilinear(p: vec2<f32>) -> vec3<f32> {
|
|
817
949
|
let size = vec2<f32>(f32(recon.renderSize.x), f32(recon.renderSize.y));
|
|
@@ -831,7 +963,9 @@ fn resolveMain(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
|
831
963
|
if (id.x >= recon.outputSize.x || id.y >= recon.outputSize.y) { return; }
|
|
832
964
|
let y = i32(recon.outputSize.y) - 1 - i32(id.y);
|
|
833
965
|
let value = reconResolvePixel(i32(id.x), y);
|
|
834
|
-
textureStore(resolved, vec2<i32>(i32(id.x), i32(id.y)), value);
|
|
966
|
+
textureStore(resolved, vec2<i32>(i32(id.x), i32(id.y)), value.colour);
|
|
967
|
+
textureStore(flickerOut, vec2<i32>(i32(id.x), i32(id.y)), value.record);
|
|
968
|
+
textureStore(swingOut, vec2<i32>(i32(id.x), i32(id.y)), vec4<f32>(value.swing, 0.0, 0.0, 0.0));
|
|
835
969
|
}
|
|
836
970
|
|
|
837
971
|
@compute @workgroup_size(${RECON_WORKGROUP}, ${RECON_WORKGROUP})
|
|
@@ -104,6 +104,16 @@ uniform float uMotionMax;
|
|
|
104
104
|
*/
|
|
105
105
|
uniform sampler2D uAo;
|
|
106
106
|
uniform float uAoStrength;
|
|
107
|
+
/**
|
|
108
|
+
* Where this frame's jitter put the picture the occlusion was measured from, in this pass's uv.
|
|
109
|
+
*
|
|
110
|
+
* The occlusion is measured from the frame's own depth, which a temporal resolve or a
|
|
111
|
+
* reconstruction jittered, and it is applied here to a picture those have already taken the jitter
|
|
112
|
+
* out of — so read at the pixel's own uv it moved by the jitter every frame, and every crevice
|
|
113
|
+
* shimmered by up to half a render texel. Read where the jitter put it, it holds still. Zero for an
|
|
114
|
+
* unjittered frame.
|
|
115
|
+
*/
|
|
116
|
+
uniform vec2 uAoOffset;
|
|
107
117
|
|
|
108
118
|
/**
|
|
109
119
|
* The bloom chain's top level, already thresholded, blurred and summed by its own pass.
|
|
@@ -341,7 +351,7 @@ void main() {
|
|
|
341
351
|
* strength, so the parameter reads as "how much of this occlusion", and 0 is exactly the
|
|
342
352
|
* frame that existed before the effect did.
|
|
343
353
|
*/
|
|
344
|
-
float ao = mix(1.0, textureLod(uAo, vUv, 0.0).r, uAoStrength);
|
|
354
|
+
float ao = mix(1.0, textureLod(uAo, vUv + uAoOffset, 0.0).r, uAoStrength);
|
|
345
355
|
|
|
346
356
|
/*
|
|
347
357
|
* Distance from the centre, corrected so the falloff is a circle on screen rather than
|
|
@@ -30,7 +30,8 @@ precision highp float;
|
|
|
30
30
|
|
|
31
31
|
in vec2 vUv;
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
/* An array of one: every surface texture is an array, and an atlas is read at layer 0. */
|
|
34
|
+
uniform mediump sampler2DArray uAtlas;
|
|
34
35
|
uniform vec3 uColor;
|
|
35
36
|
uniform float uOpacity;
|
|
36
37
|
/* Texels the field spans, from the atlas metrics. Scales the antialiasing band. */
|
|
@@ -52,7 +53,7 @@ float median(vec3 rgb) {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
void main() {
|
|
55
|
-
vec3 sampled = textureLod(uAtlas, vUv, 0.0).rgb;
|
|
56
|
+
vec3 sampled = textureLod(uAtlas, vec3(vUv, 0.0), 0.0).rgb;
|
|
56
57
|
float distance = median(sampled) - 0.5;
|
|
57
58
|
|
|
58
59
|
/*
|
|
@@ -27,7 +27,7 @@ uniform vec2 uViewport;
|
|
|
27
27
|
/** Where the string's baseline-left sits, in pixels from the top left. */
|
|
28
28
|
uniform vec2 uOrigin;
|
|
29
29
|
uniform float uCellSize;
|
|
30
|
-
/**
|
|
30
|
+
/** How far each cell is seen from, head-on; larger flattens the perspective. */
|
|
31
31
|
uniform float uDepth;
|
|
32
32
|
|
|
33
33
|
/** 0 before a character has arrived, 1 once it has settled. */
|
|
@@ -105,14 +105,23 @@ void main() {
|
|
|
105
105
|
vec2 cell = aCell * uCellSize;
|
|
106
106
|
float bob = sin(uTime * 3.1 + aCharIndex * 0.7) * uBob;
|
|
107
107
|
|
|
108
|
-
//
|
|
109
|
-
vec2
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
|
|
108
|
+
// The cell's centre in pixels, y down from the top-left corner of the viewport.
|
|
109
|
+
vec2 centre = uOrigin + vec2(cell.x, -cell.y) + vec2(0.0, rise - bob);
|
|
110
|
+
|
|
111
|
+
// A hand-built perspective divide about the cell's own centre, so every cube
|
|
112
|
+
// is seen head-on: its front face at depth zero is exactly its cell, and at
|
|
113
|
+
// rest its sides are behind it wherever on the screen it is drawn.
|
|
114
|
+
//
|
|
115
|
+
// It divided about the viewport's top-left corner until 2026-09-30, which
|
|
116
|
+
// shifted a front face by its distance from that corner times z / uDepth and
|
|
117
|
+
// showed the side it uncovered. Near the corner that was nothing; across the
|
|
118
|
+
// screen it widened every stroke by up to a pixel either side and closed the
|
|
119
|
+
// one-cell gaps a 5x7 face reads by. What this gives up is the extruded look
|
|
120
|
+
// text far from the corner had at rest; what would make it wrong is a caller
|
|
121
|
+
// wanting that look, which is then one offset for every cell, not a position.
|
|
122
|
+
float invDepth = uDepth / max(0.001, uDepth - local3.z);
|
|
123
|
+
vec2 screen = centre + local3.xy * invDepth;
|
|
124
|
+
vec2 ndc = (screen / uViewport) * 2.0 - 1.0;
|
|
116
125
|
// Depth from the cube's own extrusion, mapped into a narrow slice of the
|
|
117
126
|
// range so a message sorts against itself without ever reaching the scene.
|
|
118
127
|
float depth = clamp(-local3.z / max(1.0, uCellSize * 2.0), -1.0, 1.0) * 0.4;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { resolveGlass, type GlassOptions, type ResolvedGlass } from './glass.ts';
|
|
1
2
|
import type { ReadonlyMat4 } from 'gl-matrix';
|
|
2
3
|
import type { InstanceData } from './instancedMesh.ts';
|
|
3
4
|
import type { InstancedHandle, MeshHandle, ScatterHandle } from './backend/api.ts';
|
|
@@ -41,7 +42,33 @@ import type { SurfaceTextureHandle } from './backend/api.ts';
|
|
|
41
42
|
* outwards, so a required parameter added in a minor stops every consumer's sink and every test
|
|
42
43
|
* double compiling. A sink that ignores it behaves exactly as it did.
|
|
43
44
|
*/
|
|
44
|
-
export type SceneCasterMaterial =
|
|
45
|
+
export type SceneCasterMaterial =
|
|
46
|
+
| (SurfaceMaterial<SurfaceTextureHandle> & {
|
|
47
|
+
/**
|
|
48
|
+
* The caster is glass: it lets light through, so it writes no depth into any shadow map and a
|
|
49
|
+
* lamp behind it lights what is beyond. The colour replay into a mirror or a probe still draws
|
|
50
|
+
* it. With `RenderQuality.glassShadows` on it casts a coloured shadow instead: see
|
|
51
|
+
* `glassShadow.ts`.
|
|
52
|
+
*/
|
|
53
|
+
readonly glass?: GlassOptions;
|
|
54
|
+
})
|
|
55
|
+
| null;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Whether a caster writes depth into a shadow map: everything but glass. One line in each depth
|
|
59
|
+
* sink, so the answer is the same in every shadow a backend draws.
|
|
60
|
+
*/
|
|
61
|
+
export function castsDepth(material: SceneCasterMaterial | undefined): boolean {
|
|
62
|
+
return (material?.glass?.transmission ?? 0) <= 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The caster's glass, resolved into `out`, and whether it is glass at all — the rule `castsDepth`
|
|
67
|
+
* states from the other side, so a caster is exactly one of the two.
|
|
68
|
+
*/
|
|
69
|
+
export function glassOf(material: SceneCasterMaterial | undefined, out: ResolvedGlass): boolean {
|
|
70
|
+
return resolveGlass(material?.glass, out);
|
|
71
|
+
}
|
|
45
72
|
|
|
46
73
|
export interface ShadowCasterSink {
|
|
47
74
|
/** A rigid mesh at a model transform: the world, a prop, a static piece of scenery. */
|