@driftengine/core 4.5.0 → 4.6.1
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 +62 -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 +23 -2
- package/dist/index.js +13 -1
- package/dist/render/backend/api.d.ts +17 -3
- 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/instanced.d.ts +24 -5
- package/dist/render/backend/webgl2/instanced.js +72 -15
- package/dist/render/backend/webgl2/renderer.d.ts +122 -8
- package/dist/render/backend/webgl2/renderer.js +249 -128
- package/dist/render/backend/webgpu/buffers.d.ts +17 -0
- package/dist/render/backend/webgpu/buffers.js +34 -3
- package/dist/render/backend/webgpu/depthPass.js +5 -1
- 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 +4 -1
- package/dist/render/backend/webgpu/flatPass.js +38 -9
- package/dist/render/backend/webgpu/glassTintPass.js +2 -1
- 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 +11 -1
- package/dist/render/backend/webgpu/instanced.js +21 -3
- package/dist/render/backend/webgpu/latePass.d.ts +6 -2
- package/dist/render/backend/webgpu/latePass.js +11 -4
- package/dist/render/backend/webgpu/motionPass.js +2 -1
- package/dist/render/backend/webgpu/postPass.d.ts +1 -1
- package/dist/render/backend/webgpu/renderer.d.ts +100 -10
- package/dist/render/backend/webgpu/renderer.js +478 -214
- 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/surfaceTexturePass.d.ts +17 -3
- package/dist/render/backend/webgpu/surfaceTexturePass.js +77 -38
- 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/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 +22 -33
- package/dist/render/lightBudget.js +24 -35
- package/dist/render/lightGrid.d.ts +42 -0
- package/dist/render/lightGrid.js +87 -0
- package/dist/render/mesh.d.ts +23 -24
- package/dist/render/mesh.js +56 -68
- package/dist/render/occlusion.d.ts +10 -0
- package/dist/render/occlusion.js +36 -7
- package/dist/render/pointLightSelection.d.ts +7 -0
- package/dist/render/pointLightSelection.js +29 -4
- package/dist/render/rainField.d.ts +13 -0
- package/dist/render/rainField.js +27 -5
- package/dist/render/recon/lateDepth.d.ts +11 -0
- package/dist/render/recon/lateDepth.js +70 -0
- package/dist/render/recon/resolve.d.ts +34 -4
- package/dist/render/recon/resolve.js +161 -20
- package/dist/render/rendererHarness.js +4 -0
- package/dist/render/sceneTarget.d.ts +2 -0
- package/dist/render/sceneTarget.js +2 -0
- package/dist/render/shaders/depth.js +12 -9
- package/dist/render/shaders/flat/driftLight.d.ts +1 -1
- package/dist/render/shaders/flat/driftLight.js +32 -7
- package/dist/render/shaders/flat/index.js +5 -3
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +75 -23
- package/dist/render/shaders/flat/preamble.js +75 -20
- 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 +8 -8
- package/dist/render/shaders/generated/depth.wgsl.js +8 -8
- package/dist/render/shaders/generated/flat.wgsl.d.ts +1320 -1320
- package/dist/render/shaders/generated/flat.wgsl.js +1359 -1345
- package/dist/render/shaders/generated/lightVolume.wgsl.js +18 -4
- 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/recon/lateDepth.wgsl.js +38 -13
- 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/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/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 +51 -1
- package/src/render/backend/api.ts +21 -2
- package/src/render/backend/drawFog.ts +31 -0
- package/src/render/backend/materialChanges.ts +9 -2
- package/src/render/backend/webgl2/instanced.ts +80 -14
- package/src/render/backend/webgl2/renderer.ts +311 -150
- package/src/render/backend/webgpu/buffers.ts +49 -3
- package/src/render/backend/webgpu/depthPass.ts +5 -1
- package/src/render/backend/webgpu/drawCommand.ts +6 -0
- package/src/render/backend/webgpu/flatPass.ts +41 -11
- package/src/render/backend/webgpu/glassTintPass.ts +2 -1
- package/src/render/backend/webgpu/instanceCullPass.ts +165 -0
- package/src/render/backend/webgpu/instanced.ts +21 -3
- package/src/render/backend/webgpu/latePass.ts +12 -3
- package/src/render/backend/webgpu/motionPass.ts +2 -1
- package/src/render/backend/webgpu/renderer.ts +556 -239
- 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/surfaceTexturePass.ts +90 -50
- 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/instanceCull.ts +205 -0
- package/src/render/instances.ts +16 -0
- package/src/render/lightBudget.ts +25 -36
- package/src/render/lightGrid.ts +130 -0
- package/src/render/mesh.ts +64 -72
- package/src/render/occlusion.ts +51 -7
- package/src/render/pointLightSelection.ts +72 -4
- package/src/render/rainField.ts +39 -5
- package/src/render/recon/lateDepth.ts +83 -0
- package/src/render/recon/resolve.ts +206 -20
- package/src/render/rendererHarness.ts +4 -0
- package/src/render/sceneTarget.ts +4 -0
- package/src/render/shaders/depth.ts +12 -9
- package/src/render/shaders/flat/driftLight.ts +32 -7
- package/src/render/shaders/flat/index.ts +5 -3
- package/src/render/shaders/flat/main.ts +75 -23
- package/src/render/shaders/flat/preamble.ts +75 -20
- package/src/render/shaders/flat/surfaceEffects.ts +152 -0
- package/src/render/shaders/generated/depth.wgsl.ts +8 -8
- package/src/render/shaders/generated/flat.wgsl.ts +1361 -1345
- package/src/render/shaders/generated/lightVolume.wgsl.ts +20 -4
- 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/recon/lateDepth.wgsl.ts +38 -13
- 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/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/vertexDefaults.ts +2 -0
- package/src/world/hlod.ts +290 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const SDF_TEXT_FRAG_WGSL = "struct Uniforms {\n uColor: vec3<f32>,\n uOpacity: f32,\n uDistanceRange: f32,\n uAtlasSize: vec2<f32>,\n uOutputTransform: i32,\n uOutputExposure: f32,\n}\n\n@group(0) @binding(1) \nvar<uniform> unnamed: Uniforms;\n@group(0) @binding(32) \nvar uAtlas_t:
|
|
1
|
+
export declare const SDF_TEXT_FRAG_WGSL = "struct Uniforms {\n uColor: vec3<f32>,\n uOpacity: f32,\n uDistanceRange: f32,\n uAtlasSize: vec2<f32>,\n uOutputTransform: i32,\n uOutputExposure: f32,\n}\n\n@group(0) @binding(1) \nvar<uniform> unnamed: Uniforms;\n@group(0) @binding(32) \nvar uAtlas_t: texture_2d_array<f32>;\n@group(0) @binding(33) \nvar uAtlas_s: sampler;\nvar<private> vUv_1: vec2<f32>;\nvar<private> outColor: vec4<f32>;\n\nfn linearToSrgb_u0028_vf3_u003b(c: ptr<function, vec3<f32>>) -> vec3<f32> {\n var low: vec3<f32>;\n var high: vec3<f32>;\n\n let _e60 = (*c);\n low = (_e60 * 12.92f);\n let _e62 = (*c);\n high = ((pow(max(_e62, vec3<f32>(0f, 0f, 0f)), vec3<f32>(0.41666666f, 0.41666666f, 0.41666666f)) * 1.055f) - vec3(0.055f));\n let _e68 = high;\n let _e69 = low;\n let _e70 = (*c);\n return mix(_e68, _e69, step(_e70, vec3<f32>(0.0031308f, 0.0031308f, 0.0031308f)));\n}\n\nfn rrtAndOdtFit_u0028_vf3_u003b(v: ptr<function, vec3<f32>>) -> vec3<f32> {\n var a: vec3<f32>;\n var b: vec3<f32>;\n\n let _e60 = (*v);\n let _e61 = (*v);\n a = ((_e60 * (_e61 + vec3(0.0245786f))) - vec3(0.000090537f));\n let _e67 = (*v);\n let _e68 = (*v);\n b = ((_e67 * ((_e68 * 0.983729f) + vec3(0.432951f))) + vec3(0.238081f));\n let _e75 = a;\n let _e76 = b;\n return (_e75 / _e76);\n}\n\nfn acesFilmic_u0028_vf3_u003b(x: ptr<function, vec3<f32>>) -> vec3<f32> {\n var param: vec3<f32>;\n\n let _e60 = unnamed.uOutputExposure;\n let _e61 = (*x);\n (*x) = (_e61 * _e60);\n let _e63 = (*x);\n param = (mat3x3<f32>(vec3<f32>(0.59719f, 0.076f, 0.0284f), vec3<f32>(0.35458f, 0.90834f, 0.13383f), vec3<f32>(0.04823f, 0.01566f, 0.83777f)) * _e63);\n let _e65 = rrtAndOdtFit_u0028_vf3_u003b((¶m));\n return clamp((mat3x3<f32>(vec3<f32>(1.60475f, -0.10208f, -0.00327f), vec3<f32>(-0.53108f, 1.10813f, -0.07276f), vec3<f32>(-0.07367f, -0.00605f, 1.07602f)) * _e65), vec3(0f), vec3(1f));\n}\n\nfn applyOutputTransform_u0028_vf3_u003b(c_1: ptr<function, vec3<f32>>) -> vec3<f32> {\n var param_1: vec3<f32>;\n var param_2: vec3<f32>;\n\n let _e61 = unnamed.uOutputTransform;\n if (_e61 == 0i) {\n let _e63 = (*c_1);\n return _e63;\n }\n let _e65 = unnamed.uOutputTransform;\n if (_e65 == 2i) {\n let _e67 = (*c_1);\n param_1 = _e67;\n let _e68 = acesFilmic_u0028_vf3_u003b((¶m_1));\n (*c_1) = _e68;\n }\n let _e69 = (*c_1);\n param_2 = _e69;\n let _e70 = linearToSrgb_u0028_vf3_u003b((¶m_2));\n return _e70;\n}\n\nfn median_u0028_vf3_u003b(rgb: ptr<function, vec3<f32>>) -> f32 {\n let _e59 = (*rgb)[0u];\n let _e61 = (*rgb)[1u];\n let _e64 = (*rgb)[0u];\n let _e66 = (*rgb)[1u];\n let _e69 = (*rgb)[2u];\n return max(min(_e59, _e61), min(max(_e64, _e66), _e69));\n}\n\nfn main_1() {\n var sampled: vec3<f32>;\n var distance_: f32;\n var param_3: vec3<f32>;\n var texelsPerPixel: vec2<f32>;\n var pixelRange: f32;\n var coverage: f32;\n var param_4: vec3<f32>;\n\n let _e64 = vUv_1;\n let _e67 = vec3<f32>(_e64.x, _e64.y, 0f);\n let _e73 = textureSampleLevel(uAtlas_t, uAtlas_s, vec2<f32>(_e67.x, _e67.y), i32(_e67.z), 0f);\n sampled = _e73.xyz;\n let _e75 = sampled;\n param_3 = _e75;\n let _e76 = median_u0028_vf3_u003b((¶m_3));\n distance_ = (_e76 - 0.5f);\n let _e78 = vUv_1;\n let _e79 = fwidth(_e78);\n let _e81 = unnamed.uAtlasSize;\n texelsPerPixel = (_e79 * _e81);\n let _e84 = texelsPerPixel[0u];\n let _e86 = texelsPerPixel[1u];\n pixelRange = max((0.5f * (_e84 + _e86)), 0.0001f);\n let _e90 = distance_;\n let _e92 = unnamed.uDistanceRange;\n let _e94 = pixelRange;\n coverage = clamp((((_e90 * _e92) / _e94) + 0.5f), 0f, 1f);\n let _e99 = unnamed.uColor;\n param_4 = _e99;\n let _e100 = applyOutputTransform_u0028_vf3_u003b((¶m_4));\n let _e101 = coverage;\n let _e103 = unnamed.uOpacity;\n outColor = vec4<f32>(_e100.x, _e100.y, _e100.z, (_e101 * _e103));\n return;\n}\n\n@fragment \nfn main(@location(0) vUv: vec2<f32>) -> @location(0) vec4<f32> {\n vUv_1 = vUv;\n main_1();\n let _e3 = outColor;\n return _e3;\n}\n";
|
|
2
2
|
export declare const SDF_TEXT_VERT_WGSL = "struct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct Uniforms {\n uViewProj: mat4x4<f32>,\n uModel: mat4x4<f32>,\n}\n\nstruct VertexOutput {\n @location(0) member: vec2<f32>,\n @builtin(position) gl_Position: vec4<f32>,\n}\n\nvar<private> vUv: vec2<f32>;\nvar<private> aUv_1: vec2<f32>;\nvar<private> unnamed: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\n@group(0) @binding(0) \nvar<uniform> unnamed_1: Uniforms;\nvar<private> aPosition_1: vec3<f32>;\n\nfn main_1() {\n let _e8 = aUv_1;\n vUv = _e8;\n let _e10 = unnamed_1.uViewProj;\n let _e12 = unnamed_1.uModel;\n let _e14 = aPosition_1;\n unnamed.gl_Position = ((_e10 * _e12) * vec4<f32>(_e14.x, _e14.y, _e14.z, 1f));\n return;\n}\n\n@vertex \nfn main(@location(1) aUv: vec2<f32>, @location(0) aPosition: vec3<f32>) -> VertexOutput {\n aUv_1 = aUv;\n aPosition_1 = aPosition;\n main_1();\n let _e8 = unnamed.gl_Position.y;\n unnamed.gl_Position.y = -(_e8);\n let _e10 = vUv;\n let _e11 = unnamed.gl_Position;\n return VertexOutput(_e10, _e11);\n}\n";
|
|
3
3
|
/**
|
|
4
4
|
* What the transform assigned, so the renderer binds the same numbers.
|
|
@@ -45,7 +45,7 @@ export declare const SDFTEXT_BINDINGS: {
|
|
|
45
45
|
readonly uAtlas: {
|
|
46
46
|
readonly texture: 32;
|
|
47
47
|
readonly sampler: 33;
|
|
48
|
-
readonly type: "
|
|
48
|
+
readonly type: "sampler2DArray";
|
|
49
49
|
};
|
|
50
50
|
};
|
|
51
51
|
};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* The GLSL beside this file is the source of truth. A hand edit here is discarded by
|
|
5
5
|
* the next generation, and `npm run wgsl:check` fails the build when this is stale.
|
|
6
6
|
*/
|
|
7
|
-
export const SDF_TEXT_FRAG_WGSL = "struct Uniforms {\n uColor: vec3<f32>,\n uOpacity: f32,\n uDistanceRange: f32,\n uAtlasSize: vec2<f32>,\n uOutputTransform: i32,\n uOutputExposure: f32,\n}\n\n@group(0) @binding(1) \nvar<uniform> unnamed: Uniforms;\n@group(0) @binding(32) \nvar uAtlas_t:
|
|
7
|
+
export const SDF_TEXT_FRAG_WGSL = "struct Uniforms {\n uColor: vec3<f32>,\n uOpacity: f32,\n uDistanceRange: f32,\n uAtlasSize: vec2<f32>,\n uOutputTransform: i32,\n uOutputExposure: f32,\n}\n\n@group(0) @binding(1) \nvar<uniform> unnamed: Uniforms;\n@group(0) @binding(32) \nvar uAtlas_t: texture_2d_array<f32>;\n@group(0) @binding(33) \nvar uAtlas_s: sampler;\nvar<private> vUv_1: vec2<f32>;\nvar<private> outColor: vec4<f32>;\n\nfn linearToSrgb_u0028_vf3_u003b(c: ptr<function, vec3<f32>>) -> vec3<f32> {\n var low: vec3<f32>;\n var high: vec3<f32>;\n\n let _e60 = (*c);\n low = (_e60 * 12.92f);\n let _e62 = (*c);\n high = ((pow(max(_e62, vec3<f32>(0f, 0f, 0f)), vec3<f32>(0.41666666f, 0.41666666f, 0.41666666f)) * 1.055f) - vec3(0.055f));\n let _e68 = high;\n let _e69 = low;\n let _e70 = (*c);\n return mix(_e68, _e69, step(_e70, vec3<f32>(0.0031308f, 0.0031308f, 0.0031308f)));\n}\n\nfn rrtAndOdtFit_u0028_vf3_u003b(v: ptr<function, vec3<f32>>) -> vec3<f32> {\n var a: vec3<f32>;\n var b: vec3<f32>;\n\n let _e60 = (*v);\n let _e61 = (*v);\n a = ((_e60 * (_e61 + vec3(0.0245786f))) - vec3(0.000090537f));\n let _e67 = (*v);\n let _e68 = (*v);\n b = ((_e67 * ((_e68 * 0.983729f) + vec3(0.432951f))) + vec3(0.238081f));\n let _e75 = a;\n let _e76 = b;\n return (_e75 / _e76);\n}\n\nfn acesFilmic_u0028_vf3_u003b(x: ptr<function, vec3<f32>>) -> vec3<f32> {\n var param: vec3<f32>;\n\n let _e60 = unnamed.uOutputExposure;\n let _e61 = (*x);\n (*x) = (_e61 * _e60);\n let _e63 = (*x);\n param = (mat3x3<f32>(vec3<f32>(0.59719f, 0.076f, 0.0284f), vec3<f32>(0.35458f, 0.90834f, 0.13383f), vec3<f32>(0.04823f, 0.01566f, 0.83777f)) * _e63);\n let _e65 = rrtAndOdtFit_u0028_vf3_u003b((¶m));\n return clamp((mat3x3<f32>(vec3<f32>(1.60475f, -0.10208f, -0.00327f), vec3<f32>(-0.53108f, 1.10813f, -0.07276f), vec3<f32>(-0.07367f, -0.00605f, 1.07602f)) * _e65), vec3(0f), vec3(1f));\n}\n\nfn applyOutputTransform_u0028_vf3_u003b(c_1: ptr<function, vec3<f32>>) -> vec3<f32> {\n var param_1: vec3<f32>;\n var param_2: vec3<f32>;\n\n let _e61 = unnamed.uOutputTransform;\n if (_e61 == 0i) {\n let _e63 = (*c_1);\n return _e63;\n }\n let _e65 = unnamed.uOutputTransform;\n if (_e65 == 2i) {\n let _e67 = (*c_1);\n param_1 = _e67;\n let _e68 = acesFilmic_u0028_vf3_u003b((¶m_1));\n (*c_1) = _e68;\n }\n let _e69 = (*c_1);\n param_2 = _e69;\n let _e70 = linearToSrgb_u0028_vf3_u003b((¶m_2));\n return _e70;\n}\n\nfn median_u0028_vf3_u003b(rgb: ptr<function, vec3<f32>>) -> f32 {\n let _e59 = (*rgb)[0u];\n let _e61 = (*rgb)[1u];\n let _e64 = (*rgb)[0u];\n let _e66 = (*rgb)[1u];\n let _e69 = (*rgb)[2u];\n return max(min(_e59, _e61), min(max(_e64, _e66), _e69));\n}\n\nfn main_1() {\n var sampled: vec3<f32>;\n var distance_: f32;\n var param_3: vec3<f32>;\n var texelsPerPixel: vec2<f32>;\n var pixelRange: f32;\n var coverage: f32;\n var param_4: vec3<f32>;\n\n let _e64 = vUv_1;\n let _e67 = vec3<f32>(_e64.x, _e64.y, 0f);\n let _e73 = textureSampleLevel(uAtlas_t, uAtlas_s, vec2<f32>(_e67.x, _e67.y), i32(_e67.z), 0f);\n sampled = _e73.xyz;\n let _e75 = sampled;\n param_3 = _e75;\n let _e76 = median_u0028_vf3_u003b((¶m_3));\n distance_ = (_e76 - 0.5f);\n let _e78 = vUv_1;\n let _e79 = fwidth(_e78);\n let _e81 = unnamed.uAtlasSize;\n texelsPerPixel = (_e79 * _e81);\n let _e84 = texelsPerPixel[0u];\n let _e86 = texelsPerPixel[1u];\n pixelRange = max((0.5f * (_e84 + _e86)), 0.0001f);\n let _e90 = distance_;\n let _e92 = unnamed.uDistanceRange;\n let _e94 = pixelRange;\n coverage = clamp((((_e90 * _e92) / _e94) + 0.5f), 0f, 1f);\n let _e99 = unnamed.uColor;\n param_4 = _e99;\n let _e100 = applyOutputTransform_u0028_vf3_u003b((¶m_4));\n let _e101 = coverage;\n let _e103 = unnamed.uOpacity;\n outColor = vec4<f32>(_e100.x, _e100.y, _e100.z, (_e101 * _e103));\n return;\n}\n\n@fragment \nfn main(@location(0) vUv: vec2<f32>) -> @location(0) vec4<f32> {\n vUv_1 = vUv;\n main_1();\n let _e3 = outColor;\n return _e3;\n}\n";
|
|
8
8
|
export const SDF_TEXT_VERT_WGSL = "struct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct Uniforms {\n uViewProj: mat4x4<f32>,\n uModel: mat4x4<f32>,\n}\n\nstruct VertexOutput {\n @location(0) member: vec2<f32>,\n @builtin(position) gl_Position: vec4<f32>,\n}\n\nvar<private> vUv: vec2<f32>;\nvar<private> aUv_1: vec2<f32>;\nvar<private> unnamed: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\n@group(0) @binding(0) \nvar<uniform> unnamed_1: Uniforms;\nvar<private> aPosition_1: vec3<f32>;\n\nfn main_1() {\n let _e8 = aUv_1;\n vUv = _e8;\n let _e10 = unnamed_1.uViewProj;\n let _e12 = unnamed_1.uModel;\n let _e14 = aPosition_1;\n unnamed.gl_Position = ((_e10 * _e12) * vec4<f32>(_e14.x, _e14.y, _e14.z, 1f));\n return;\n}\n\n@vertex \nfn main(@location(1) aUv: vec2<f32>, @location(0) aPosition: vec3<f32>) -> VertexOutput {\n aUv_1 = aUv;\n aPosition_1 = aPosition;\n main_1();\n let _e8 = unnamed.gl_Position.y;\n unnamed.gl_Position.y = -(_e8);\n let _e10 = vUv;\n let _e11 = unnamed.gl_Position;\n return VertexOutput(_e10, _e11);\n}\n";
|
|
9
9
|
/**
|
|
10
10
|
* What the transform assigned, so the renderer binds the same numbers.
|
|
@@ -51,7 +51,7 @@ export const SDFTEXT_BINDINGS = {
|
|
|
51
51
|
"uAtlas": {
|
|
52
52
|
"texture": 32,
|
|
53
53
|
"sampler": 33,
|
|
54
|
-
"type": "
|
|
54
|
+
"type": "sampler2DArray"
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const TEXT_FRAG_WGSL = "struct Uniforms {\n uColor: vec3<f32>,\n uGlow: f32,\n uAlpha: f32,\n}\n\nvar<private> vNormal_1: vec3<f32>;\n@group(0) @binding(1) \nvar<uniform> unnamed: Uniforms;\nvar<private> vChar_1: f32;\nvar<private> fragColor: vec4<f32>;\nvar<private> vDepth_1: f32;\n\nfn main_1() {\n var key: vec3<f32>;\n var lambert: f32;\n var lit: vec3<f32>;\n var emissive: vec3<f32>;\n\n key = vec3<f32>(-0.3549141f, 0.7098282f, 0.6084241f);\n let _e19 = vNormal_1;\n let _e21 = key;\n lambert = (0.55f + (0.45f * max(dot(normalize(_e19), _e21), 0f)));\n let _e27 = unnamed.uColor;\n let _e28 = lambert;\n lit = (_e27 * _e28);\n let _e31 = unnamed.uColor;\n let _e33 = unnamed.uGlow;\n let _e35 = vChar_1;\n emissive = ((_e31 * _e33) * (0.45f + (0.55f * _e35)));\n let _e39 = lit;\n let _e40 = emissive;\n let _e41 = (_e39 + _e40);\n let _e43 = unnamed.uAlpha;\n fragColor = vec4<f32>(_e41.x, _e41.y, _e41.z, _e43);\n return;\n}\n\n@fragment \nfn main(@location(0) vNormal: vec3<f32>, @location(2) vChar: f32, @location(1) vDepth: f32) -> @location(0) vec4<f32> {\n vNormal_1 = vNormal;\n vChar_1 = vChar;\n vDepth_1 = vDepth;\n main_1();\n let _e7 = fragColor;\n return _e7;\n}\n";
|
|
2
|
-
export declare const TEXT_VERT_WGSL = "struct Uniforms {\n uViewport: vec2<f32>,\n uOrigin: vec2<f32>,\n uCellSize: f32,\n uDepth: f32,\n uReveal: f32,\n uCharCount: f32,\n uCharOffset: f32,\n uSpin: f32,\n uPunch: f32,\n uBob: f32,\n uTime: f32,\n uClipCorrection: mat4x4<f32>,\n}\n\nstruct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct VertexOutput {\n @builtin(position) gl_Position: vec4<f32>,\n @location(0) member: vec3<f32>,\n @location(1) member_1: f32,\n @location(2) member_2: f32,\n}\n\n@group(0) @binding(0) \nvar<uniform> unnamed: Uniforms;\nvar<private> aCharIndex_1: f32;\nvar<private> aCorner_1: vec3<f32>;\nvar<private> aCell_1: vec2<f32>;\nvar<private> unnamed_1: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\nvar<private> aNormal_1: vec3<f32>;\nvar<private> vNormal: vec3<f32>;\nvar<private> vDepth: f32;\nvar<private> vChar: f32;\n\nfn rot_u0028_f1_u003b(a: ptr<function, f32>) -> mat2x2<f32> {\n var s: f32;\n var c: f32;\n\n let _e40 = (*a);\n s = sin(_e40);\n let _e42 = (*a);\n c = cos(_e42);\n let _e44 = c;\n let _e45 = s;\n let _e47 = s;\n let _e48 = c;\n return mat2x2<f32>(vec2<f32>(_e44, -(_e45)), vec2<f32>(_e47, _e48));\n}\n\nfn settle_u0028_f1_u003b(t: ptr<function, f32>) -> f32 {\n var d: f32;\n\n let _e39 = (*t);\n if (_e39 <= 0f) {\n return 0f;\n }\n let _e41 = (*t);\n if (_e41 >= 1f) {\n return 1f;\n }\n let _e43 = (*t);\n d = (1f - _e43);\n let _e45 = d;\n let _e46 = d;\n let _e48 = (*t);\n return (1f - ((_e45 * _e46) * cos((_e48 * 12f))));\n}\n\nfn main_1() {\n var span: f32;\n var start: f32;\n var local: f32;\n var eased: f32;\n var param: f32;\n var spin: f32;\n var rise: f32;\n var punch: f32;\n var local3_: vec3<f32>;\n var param_1: f32;\n var cell: vec2<f32>;\n var bob: f32;\n var
|
|
2
|
+
export declare const TEXT_VERT_WGSL = "struct Uniforms {\n uViewport: vec2<f32>,\n uOrigin: vec2<f32>,\n uCellSize: f32,\n uDepth: f32,\n uReveal: f32,\n uCharCount: f32,\n uCharOffset: f32,\n uSpin: f32,\n uPunch: f32,\n uBob: f32,\n uTime: f32,\n uClipCorrection: mat4x4<f32>,\n}\n\nstruct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct VertexOutput {\n @builtin(position) gl_Position: vec4<f32>,\n @location(0) member: vec3<f32>,\n @location(1) member_1: f32,\n @location(2) member_2: f32,\n}\n\n@group(0) @binding(0) \nvar<uniform> unnamed: Uniforms;\nvar<private> aCharIndex_1: f32;\nvar<private> aCorner_1: vec3<f32>;\nvar<private> aCell_1: vec2<f32>;\nvar<private> unnamed_1: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\nvar<private> aNormal_1: vec3<f32>;\nvar<private> vNormal: vec3<f32>;\nvar<private> vDepth: f32;\nvar<private> vChar: f32;\n\nfn rot_u0028_f1_u003b(a: ptr<function, f32>) -> mat2x2<f32> {\n var s: f32;\n var c: f32;\n\n let _e40 = (*a);\n s = sin(_e40);\n let _e42 = (*a);\n c = cos(_e42);\n let _e44 = c;\n let _e45 = s;\n let _e47 = s;\n let _e48 = c;\n return mat2x2<f32>(vec2<f32>(_e44, -(_e45)), vec2<f32>(_e47, _e48));\n}\n\nfn settle_u0028_f1_u003b(t: ptr<function, f32>) -> f32 {\n var d: f32;\n\n let _e39 = (*t);\n if (_e39 <= 0f) {\n return 0f;\n }\n let _e41 = (*t);\n if (_e41 >= 1f) {\n return 1f;\n }\n let _e43 = (*t);\n d = (1f - _e43);\n let _e45 = d;\n let _e46 = d;\n let _e48 = (*t);\n return (1f - ((_e45 * _e46) * cos((_e48 * 12f))));\n}\n\nfn main_1() {\n var span: f32;\n var start: f32;\n var local: f32;\n var eased: f32;\n var param: f32;\n var spin: f32;\n var rise: f32;\n var punch: f32;\n var local3_: vec3<f32>;\n var param_1: f32;\n var cell: vec2<f32>;\n var bob: f32;\n var centre: vec2<f32>;\n var invDepth: f32;\n var screen: vec2<f32>;\n var ndc: vec2<f32>;\n var depth: f32;\n var n: vec3<f32>;\n var param_2: f32;\n\n let _e57 = unnamed.uCharCount;\n span = max(_e57, 1f);\n let _e59 = aCharIndex_1;\n let _e61 = unnamed.uCharOffset;\n let _e63 = span;\n start = (((_e59 + _e61) / _e63) * 0.55f);\n let _e67 = unnamed.uReveal;\n let _e68 = start;\n let _e70 = start;\n local = clamp(((_e67 - _e68) / max(0.45f, (1f - _e70))), 0f, 1f);\n let _e75 = local;\n param = _e75;\n let _e76 = settle_u0028_f1_u003b((¶m));\n eased = _e76;\n let _e78 = unnamed.uSpin;\n let _e79 = eased;\n spin = (_e78 * (1f - _e79));\n let _e82 = eased;\n let _e85 = unnamed.uCellSize;\n rise = (((1f - _e82) * _e85) * 6f);\n let _e89 = unnamed.uPunch;\n let _e90 = eased;\n punch = (1f + (_e89 * (1f - abs(((_e90 * 2f) - 1f)))));\n let _e97 = aCorner_1;\n let _e99 = unnamed.uCellSize;\n let _e102 = punch;\n local3_ = (((_e97 * _e99) * 0.5f) * _e102);\n let _e104 = spin;\n param_1 = _e104;\n let _e105 = rot_u0028_f1_u003b((¶m_1));\n let _e106 = local3_;\n let _e108 = (_e105 * _e106.yz);\n let _e109 = local3_;\n local3_ = vec3<f32>(_e109.x, _e108.x, _e108.y);\n let _e114 = aCell_1;\n let _e116 = unnamed.uCellSize;\n cell = (_e114 * _e116);\n let _e119 = unnamed.uTime;\n let _e121 = aCharIndex_1;\n let _e126 = unnamed.uBob;\n bob = (sin(((_e119 * 3.1f) + (_e121 * 0.7f))) * _e126);\n let _e129 = unnamed.uOrigin;\n let _e131 = cell[0u];\n let _e133 = cell[1u];\n let _e137 = rise;\n let _e138 = bob;\n centre = ((_e129 + vec2<f32>(_e131, -(_e133))) + vec2<f32>(0f, (_e137 - _e138)));\n let _e143 = unnamed.uDepth;\n let _e145 = unnamed.uDepth;\n let _e147 = local3_[2u];\n invDepth = (_e143 / max(0.001f, (_e145 - _e147)));\n let _e151 = centre;\n let _e152 = local3_;\n let _e154 = invDepth;\n screen = (_e151 + (_e152.xy * _e154));\n let _e157 = screen;\n let _e159 = unnamed.uViewport;\n ndc = (((_e157 / _e159) * 2f) - vec2(1f));\n let _e165 = local3_[2u];\n let _e168 = unnamed.uCellSize;\n depth = (clamp((-(_e165) / max(1f, (_e168 * 2f))), -1f, 1f) * 0.4f);\n let _e175 = unnamed.uClipCorrection;\n let _e177 = ndc[0u];\n let _e179 = ndc[1u];\n let _e181 = depth;\n unnamed_1.gl_Position = (_e175 * vec4<f32>(_e177, -(_e179), _e181, 1f));\n let _e185 = aNormal_1;\n n = _e185;\n let _e186 = spin;\n param_2 = _e186;\n let _e187 = rot_u0028_f1_u003b((¶m_2));\n let _e188 = n;\n let _e190 = (_e187 * _e188.yz);\n let _e191 = n;\n n = vec3<f32>(_e191.x, _e190.x, _e190.y);\n let _e196 = n;\n vNormal = _e196;\n let _e198 = local3_[2u];\n vDepth = _e198;\n let _e199 = eased;\n vChar = _e199;\n return;\n}\n\n@vertex \nfn main(@location(3) aCharIndex: f32, @location(0) aCorner: vec3<f32>, @location(2) aCell: vec2<f32>, @location(1) aNormal: vec3<f32>) -> VertexOutput {\n aCharIndex_1 = aCharIndex;\n aCorner_1 = aCorner;\n aCell_1 = aCell;\n aNormal_1 = aNormal;\n main_1();\n let _e14 = unnamed_1.gl_Position.y;\n unnamed_1.gl_Position.y = -(_e14);\n let _e16 = unnamed_1.gl_Position;\n let _e17 = vNormal;\n let _e18 = vDepth;\n let _e19 = vChar;\n return VertexOutput(_e16, _e17, _e18, _e19);\n}\n";
|
|
3
3
|
/**
|
|
4
4
|
* What the transform assigned, so the renderer binds the same numbers.
|
|
5
5
|
*
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* the next generation, and `npm run wgsl:check` fails the build when this is stale.
|
|
6
6
|
*/
|
|
7
7
|
export const TEXT_FRAG_WGSL = "struct Uniforms {\n uColor: vec3<f32>,\n uGlow: f32,\n uAlpha: f32,\n}\n\nvar<private> vNormal_1: vec3<f32>;\n@group(0) @binding(1) \nvar<uniform> unnamed: Uniforms;\nvar<private> vChar_1: f32;\nvar<private> fragColor: vec4<f32>;\nvar<private> vDepth_1: f32;\n\nfn main_1() {\n var key: vec3<f32>;\n var lambert: f32;\n var lit: vec3<f32>;\n var emissive: vec3<f32>;\n\n key = vec3<f32>(-0.3549141f, 0.7098282f, 0.6084241f);\n let _e19 = vNormal_1;\n let _e21 = key;\n lambert = (0.55f + (0.45f * max(dot(normalize(_e19), _e21), 0f)));\n let _e27 = unnamed.uColor;\n let _e28 = lambert;\n lit = (_e27 * _e28);\n let _e31 = unnamed.uColor;\n let _e33 = unnamed.uGlow;\n let _e35 = vChar_1;\n emissive = ((_e31 * _e33) * (0.45f + (0.55f * _e35)));\n let _e39 = lit;\n let _e40 = emissive;\n let _e41 = (_e39 + _e40);\n let _e43 = unnamed.uAlpha;\n fragColor = vec4<f32>(_e41.x, _e41.y, _e41.z, _e43);\n return;\n}\n\n@fragment \nfn main(@location(0) vNormal: vec3<f32>, @location(2) vChar: f32, @location(1) vDepth: f32) -> @location(0) vec4<f32> {\n vNormal_1 = vNormal;\n vChar_1 = vChar;\n vDepth_1 = vDepth;\n main_1();\n let _e7 = fragColor;\n return _e7;\n}\n";
|
|
8
|
-
export const TEXT_VERT_WGSL = "struct Uniforms {\n uViewport: vec2<f32>,\n uOrigin: vec2<f32>,\n uCellSize: f32,\n uDepth: f32,\n uReveal: f32,\n uCharCount: f32,\n uCharOffset: f32,\n uSpin: f32,\n uPunch: f32,\n uBob: f32,\n uTime: f32,\n uClipCorrection: mat4x4<f32>,\n}\n\nstruct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct VertexOutput {\n @builtin(position) gl_Position: vec4<f32>,\n @location(0) member: vec3<f32>,\n @location(1) member_1: f32,\n @location(2) member_2: f32,\n}\n\n@group(0) @binding(0) \nvar<uniform> unnamed: Uniforms;\nvar<private> aCharIndex_1: f32;\nvar<private> aCorner_1: vec3<f32>;\nvar<private> aCell_1: vec2<f32>;\nvar<private> unnamed_1: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\nvar<private> aNormal_1: vec3<f32>;\nvar<private> vNormal: vec3<f32>;\nvar<private> vDepth: f32;\nvar<private> vChar: f32;\n\nfn rot_u0028_f1_u003b(a: ptr<function, f32>) -> mat2x2<f32> {\n var s: f32;\n var c: f32;\n\n let _e40 = (*a);\n s = sin(_e40);\n let _e42 = (*a);\n c = cos(_e42);\n let _e44 = c;\n let _e45 = s;\n let _e47 = s;\n let _e48 = c;\n return mat2x2<f32>(vec2<f32>(_e44, -(_e45)), vec2<f32>(_e47, _e48));\n}\n\nfn settle_u0028_f1_u003b(t: ptr<function, f32>) -> f32 {\n var d: f32;\n\n let _e39 = (*t);\n if (_e39 <= 0f) {\n return 0f;\n }\n let _e41 = (*t);\n if (_e41 >= 1f) {\n return 1f;\n }\n let _e43 = (*t);\n d = (1f - _e43);\n let _e45 = d;\n let _e46 = d;\n let _e48 = (*t);\n return (1f - ((_e45 * _e46) * cos((_e48 * 12f))));\n}\n\nfn main_1() {\n var span: f32;\n var start: f32;\n var local: f32;\n var eased: f32;\n var param: f32;\n var spin: f32;\n var rise: f32;\n var punch: f32;\n var local3_: vec3<f32>;\n var param_1: f32;\n var cell: vec2<f32>;\n var bob: f32;\n var
|
|
8
|
+
export const TEXT_VERT_WGSL = "struct Uniforms {\n uViewport: vec2<f32>,\n uOrigin: vec2<f32>,\n uCellSize: f32,\n uDepth: f32,\n uReveal: f32,\n uCharCount: f32,\n uCharOffset: f32,\n uSpin: f32,\n uPunch: f32,\n uBob: f32,\n uTime: f32,\n uClipCorrection: mat4x4<f32>,\n}\n\nstruct gl_PerVertex {\n @builtin(position) gl_Position: vec4<f32>,\n gl_PointSize: f32,\n}\n\nstruct VertexOutput {\n @builtin(position) gl_Position: vec4<f32>,\n @location(0) member: vec3<f32>,\n @location(1) member_1: f32,\n @location(2) member_2: f32,\n}\n\n@group(0) @binding(0) \nvar<uniform> unnamed: Uniforms;\nvar<private> aCharIndex_1: f32;\nvar<private> aCorner_1: vec3<f32>;\nvar<private> aCell_1: vec2<f32>;\nvar<private> unnamed_1: gl_PerVertex = gl_PerVertex(vec4<f32>(0f, 0f, 0f, 1f), 1f);\nvar<private> aNormal_1: vec3<f32>;\nvar<private> vNormal: vec3<f32>;\nvar<private> vDepth: f32;\nvar<private> vChar: f32;\n\nfn rot_u0028_f1_u003b(a: ptr<function, f32>) -> mat2x2<f32> {\n var s: f32;\n var c: f32;\n\n let _e40 = (*a);\n s = sin(_e40);\n let _e42 = (*a);\n c = cos(_e42);\n let _e44 = c;\n let _e45 = s;\n let _e47 = s;\n let _e48 = c;\n return mat2x2<f32>(vec2<f32>(_e44, -(_e45)), vec2<f32>(_e47, _e48));\n}\n\nfn settle_u0028_f1_u003b(t: ptr<function, f32>) -> f32 {\n var d: f32;\n\n let _e39 = (*t);\n if (_e39 <= 0f) {\n return 0f;\n }\n let _e41 = (*t);\n if (_e41 >= 1f) {\n return 1f;\n }\n let _e43 = (*t);\n d = (1f - _e43);\n let _e45 = d;\n let _e46 = d;\n let _e48 = (*t);\n return (1f - ((_e45 * _e46) * cos((_e48 * 12f))));\n}\n\nfn main_1() {\n var span: f32;\n var start: f32;\n var local: f32;\n var eased: f32;\n var param: f32;\n var spin: f32;\n var rise: f32;\n var punch: f32;\n var local3_: vec3<f32>;\n var param_1: f32;\n var cell: vec2<f32>;\n var bob: f32;\n var centre: vec2<f32>;\n var invDepth: f32;\n var screen: vec2<f32>;\n var ndc: vec2<f32>;\n var depth: f32;\n var n: vec3<f32>;\n var param_2: f32;\n\n let _e57 = unnamed.uCharCount;\n span = max(_e57, 1f);\n let _e59 = aCharIndex_1;\n let _e61 = unnamed.uCharOffset;\n let _e63 = span;\n start = (((_e59 + _e61) / _e63) * 0.55f);\n let _e67 = unnamed.uReveal;\n let _e68 = start;\n let _e70 = start;\n local = clamp(((_e67 - _e68) / max(0.45f, (1f - _e70))), 0f, 1f);\n let _e75 = local;\n param = _e75;\n let _e76 = settle_u0028_f1_u003b((¶m));\n eased = _e76;\n let _e78 = unnamed.uSpin;\n let _e79 = eased;\n spin = (_e78 * (1f - _e79));\n let _e82 = eased;\n let _e85 = unnamed.uCellSize;\n rise = (((1f - _e82) * _e85) * 6f);\n let _e89 = unnamed.uPunch;\n let _e90 = eased;\n punch = (1f + (_e89 * (1f - abs(((_e90 * 2f) - 1f)))));\n let _e97 = aCorner_1;\n let _e99 = unnamed.uCellSize;\n let _e102 = punch;\n local3_ = (((_e97 * _e99) * 0.5f) * _e102);\n let _e104 = spin;\n param_1 = _e104;\n let _e105 = rot_u0028_f1_u003b((¶m_1));\n let _e106 = local3_;\n let _e108 = (_e105 * _e106.yz);\n let _e109 = local3_;\n local3_ = vec3<f32>(_e109.x, _e108.x, _e108.y);\n let _e114 = aCell_1;\n let _e116 = unnamed.uCellSize;\n cell = (_e114 * _e116);\n let _e119 = unnamed.uTime;\n let _e121 = aCharIndex_1;\n let _e126 = unnamed.uBob;\n bob = (sin(((_e119 * 3.1f) + (_e121 * 0.7f))) * _e126);\n let _e129 = unnamed.uOrigin;\n let _e131 = cell[0u];\n let _e133 = cell[1u];\n let _e137 = rise;\n let _e138 = bob;\n centre = ((_e129 + vec2<f32>(_e131, -(_e133))) + vec2<f32>(0f, (_e137 - _e138)));\n let _e143 = unnamed.uDepth;\n let _e145 = unnamed.uDepth;\n let _e147 = local3_[2u];\n invDepth = (_e143 / max(0.001f, (_e145 - _e147)));\n let _e151 = centre;\n let _e152 = local3_;\n let _e154 = invDepth;\n screen = (_e151 + (_e152.xy * _e154));\n let _e157 = screen;\n let _e159 = unnamed.uViewport;\n ndc = (((_e157 / _e159) * 2f) - vec2(1f));\n let _e165 = local3_[2u];\n let _e168 = unnamed.uCellSize;\n depth = (clamp((-(_e165) / max(1f, (_e168 * 2f))), -1f, 1f) * 0.4f);\n let _e175 = unnamed.uClipCorrection;\n let _e177 = ndc[0u];\n let _e179 = ndc[1u];\n let _e181 = depth;\n unnamed_1.gl_Position = (_e175 * vec4<f32>(_e177, -(_e179), _e181, 1f));\n let _e185 = aNormal_1;\n n = _e185;\n let _e186 = spin;\n param_2 = _e186;\n let _e187 = rot_u0028_f1_u003b((¶m_2));\n let _e188 = n;\n let _e190 = (_e187 * _e188.yz);\n let _e191 = n;\n n = vec3<f32>(_e191.x, _e190.x, _e190.y);\n let _e196 = n;\n vNormal = _e196;\n let _e198 = local3_[2u];\n vDepth = _e198;\n let _e199 = eased;\n vChar = _e199;\n return;\n}\n\n@vertex \nfn main(@location(3) aCharIndex: f32, @location(0) aCorner: vec3<f32>, @location(2) aCell: vec2<f32>, @location(1) aNormal: vec3<f32>) -> VertexOutput {\n aCharIndex_1 = aCharIndex;\n aCorner_1 = aCorner;\n aCell_1 = aCell;\n aNormal_1 = aNormal;\n main_1();\n let _e14 = unnamed_1.gl_Position.y;\n unnamed_1.gl_Position.y = -(_e14);\n let _e16 = unnamed_1.gl_Position;\n let _e17 = vNormal;\n let _e18 = vDepth;\n let _e19 = vChar;\n return VertexOutput(_e16, _e17, _e18, _e19);\n}\n";
|
|
9
9
|
/**
|
|
10
10
|
* What the transform assigned, so the renderer binds the same numbers.
|
|
11
11
|
*
|
|
@@ -13,4 +13,4 @@
|
|
|
13
13
|
* The including module declares `driftIndex: texture_3d<u32>`, `driftAtlas: texture_3d<f32>` and a
|
|
14
14
|
* filtering `driftSampler`; `origin` is the field's first sample and, in `w`, the spacing.
|
|
15
15
|
*/
|
|
16
|
-
export declare const DRIFT_LIGHT_WGSL = "\nfn driftLightIrradiance(world: vec3<f32>, n: vec3<f32>, origin: vec4<f32>) -> vec3<f32> {\n let spacing = origin.w;\n let at = (world + n * (0.5 * spacing) - origin.xyz) / (3.0 * spacing);\n let cell = vec3<i32>(floor(at));\n if (any(cell < vec3<i32>(0)) || any(cell >= vec3<i32>(textureDimensions(driftIndex, 0)))) {\n return vec3<f32>(0.0);\n }\n let id = textureLoad(driftIndex, cell, 0).r;\n if (id == 0u) {\n return vec3<f32>(0.0);\n }\n let size = vec3<i32>(textureDimensions(driftAtlas, 0));\n let brick = i32(id) - 1;\n let across = size.x / 8;\n let down = size.y / 4;\n let corner = vec3<f32>(\n f32((brick % across) * 8),\n f32(((brick / across) % down) * 4),\n f32((brick / (across * down)) * 4)\n );\n let texel = 1.0 / vec3<f32>(size);\n let inside = (at - vec3<f32>(cell)) * 3.0 + 0.5;\n let light = textureSampleLevel(driftAtlas, driftSampler, (corner + inside) * texel, 0.0);\n if (light.a < 1e-3) {\n return vec3<f32>(0.0);\n }\n let toward = textureSampleLevel(driftAtlas, driftSampler, (corner + vec3<f32>(4.0, 0.0, 0.0) + inside) * texel, 0.0);\n
|
|
16
|
+
export declare const DRIFT_LIGHT_WGSL = "\nfn driftLightFacing(light: vec4<f32>, toward: vec4<f32>, n: vec3<f32>) -> vec3<f32> {\n let arriving = light.rgb / light.a;\n let towardLight = toward.xyz / light.a;\n let facing = max(dot(n, towardLight), 0.0) + (1.0 - min(length(towardLight), 1.0)) * 0.25;\n return arriving * facing;\n}\n\nfn driftLightDense(world: vec3<f32>, n: vec3<f32>, origin: vec4<f32>, spacing: f32) -> vec3<f32> {\n let size = vec3<i32>(textureDimensions(driftAtlas, 0));\n let dims = vec3<f32>(f32(size.x), f32(size.y / 2), f32(size.z));\n let at = (world + n * (0.5 * spacing) - origin.xyz) / spacing;\n if (any(at < vec3<f32>(0.0)) || any(at > dims - 1.0)) {\n return vec3<f32>(0.0);\n }\n let uvw = (at + 0.5) / vec3<f32>(dims.x, dims.y * 2.0, dims.z);\n let light = textureSampleLevel(driftAtlas, driftSampler, uvw, 0.0);\n if (light.a < 1e-3) {\n return vec3<f32>(0.0);\n }\n let toward = textureSampleLevel(driftAtlas, driftSampler, uvw + vec3<f32>(0.0, 0.5, 0.0), 0.0);\n return driftLightFacing(light, toward, n);\n}\n\nfn driftLightIrradiance(world: vec3<f32>, n: vec3<f32>, origin: vec4<f32>) -> vec3<f32> {\n let spacing = origin.w;\n if (spacing < 0.0) {\n return driftLightDense(world, n, origin, -spacing);\n }\n let at = (world + n * (0.5 * spacing) - origin.xyz) / (3.0 * spacing);\n let cell = vec3<i32>(floor(at));\n if (any(cell < vec3<i32>(0)) || any(cell >= vec3<i32>(textureDimensions(driftIndex, 0)))) {\n return vec3<f32>(0.0);\n }\n let id = textureLoad(driftIndex, cell, 0).r;\n if (id == 0u) {\n return vec3<f32>(0.0);\n }\n let size = vec3<i32>(textureDimensions(driftAtlas, 0));\n let brick = i32(id) - 1;\n let across = size.x / 8;\n let down = size.y / 4;\n let corner = vec3<f32>(\n f32((brick % across) * 8),\n f32(((brick / across) % down) * 4),\n f32((brick / (across * down)) * 4)\n );\n let texel = 1.0 / vec3<f32>(size);\n let inside = (at - vec3<f32>(cell)) * 3.0 + 0.5;\n let light = textureSampleLevel(driftAtlas, driftSampler, (corner + inside) * texel, 0.0);\n if (light.a < 1e-3) {\n return vec3<f32>(0.0);\n }\n let toward = textureSampleLevel(driftAtlas, driftSampler, (corner + vec3<f32>(4.0, 0.0, 0.0) + inside) * texel, 0.0);\n return driftLightFacing(light, toward, n);\n}\n";
|
|
@@ -14,8 +14,34 @@
|
|
|
14
14
|
* filtering `driftSampler`; `origin` is the field's first sample and, in `w`, the spacing.
|
|
15
15
|
*/
|
|
16
16
|
export const DRIFT_LIGHT_WGSL = /* wgsl */ `
|
|
17
|
+
fn driftLightFacing(light: vec4<f32>, toward: vec4<f32>, n: vec3<f32>) -> vec3<f32> {
|
|
18
|
+
let arriving = light.rgb / light.a;
|
|
19
|
+
let towardLight = toward.xyz / light.a;
|
|
20
|
+
let facing = max(dot(n, towardLight), 0.0) + (1.0 - min(length(towardLight), 1.0)) * 0.25;
|
|
21
|
+
return arriving * facing;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fn driftLightDense(world: vec3<f32>, n: vec3<f32>, origin: vec4<f32>, spacing: f32) -> vec3<f32> {
|
|
25
|
+
let size = vec3<i32>(textureDimensions(driftAtlas, 0));
|
|
26
|
+
let dims = vec3<f32>(f32(size.x), f32(size.y / 2), f32(size.z));
|
|
27
|
+
let at = (world + n * (0.5 * spacing) - origin.xyz) / spacing;
|
|
28
|
+
if (any(at < vec3<f32>(0.0)) || any(at > dims - 1.0)) {
|
|
29
|
+
return vec3<f32>(0.0);
|
|
30
|
+
}
|
|
31
|
+
let uvw = (at + 0.5) / vec3<f32>(dims.x, dims.y * 2.0, dims.z);
|
|
32
|
+
let light = textureSampleLevel(driftAtlas, driftSampler, uvw, 0.0);
|
|
33
|
+
if (light.a < 1e-3) {
|
|
34
|
+
return vec3<f32>(0.0);
|
|
35
|
+
}
|
|
36
|
+
let toward = textureSampleLevel(driftAtlas, driftSampler, uvw + vec3<f32>(0.0, 0.5, 0.0), 0.0);
|
|
37
|
+
return driftLightFacing(light, toward, n);
|
|
38
|
+
}
|
|
39
|
+
|
|
17
40
|
fn driftLightIrradiance(world: vec3<f32>, n: vec3<f32>, origin: vec4<f32>) -> vec3<f32> {
|
|
18
41
|
let spacing = origin.w;
|
|
42
|
+
if (spacing < 0.0) {
|
|
43
|
+
return driftLightDense(world, n, origin, -spacing);
|
|
44
|
+
}
|
|
19
45
|
let at = (world + n * (0.5 * spacing) - origin.xyz) / (3.0 * spacing);
|
|
20
46
|
let cell = vec3<i32>(floor(at));
|
|
21
47
|
if (any(cell < vec3<i32>(0)) || any(cell >= vec3<i32>(textureDimensions(driftIndex, 0)))) {
|
|
@@ -41,9 +67,6 @@ fn driftLightIrradiance(world: vec3<f32>, n: vec3<f32>, origin: vec4<f32>) -> ve
|
|
|
41
67
|
return vec3<f32>(0.0);
|
|
42
68
|
}
|
|
43
69
|
let toward = textureSampleLevel(driftAtlas, driftSampler, (corner + vec3<f32>(4.0, 0.0, 0.0) + inside) * texel, 0.0);
|
|
44
|
-
|
|
45
|
-
let towardLight = toward.xyz / light.a;
|
|
46
|
-
let facing = max(dot(n, towardLight), 0.0) + (1.0 - min(length(towardLight), 1.0)) * 0.25;
|
|
47
|
-
return arriving * facing;
|
|
70
|
+
return driftLightFacing(light, toward, n);
|
|
48
71
|
}
|
|
49
72
|
`;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The render's depth, taken up to the output size for the draws that land after the upscale.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
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.
|
|
7
10
|
*
|
|
8
11
|
* Hand-written, and built by concatenation rather than a template literal: the reconstruction's
|
|
9
12
|
* passes have no WebGL2 twin (the AGENTS.md exception for them), and a `${}` inside WGSL source is
|
|
@@ -12,10 +15,13 @@
|
|
|
12
15
|
import { REVERSED_DEPTH } from '../../depthConvention.js';
|
|
13
16
|
/** The nearer of two stored depths: the larger in a reversed buffer. */
|
|
14
17
|
const NEARER = REVERSED_DEPTH ? 'max' : 'min';
|
|
18
|
+
/** Toward the far side: down in a reversed buffer. */
|
|
19
|
+
const FARWARD = REVERSED_DEPTH ? '-' : '+';
|
|
15
20
|
/** Where the search for the nearest starts: the far plane. */
|
|
16
21
|
const FARTHEST = REVERSED_DEPTH ? '0.0' : '1.0';
|
|
17
22
|
export const LATE_DEPTH_WGSL = '@group(0) @binding(0) var source: texture_depth_2d;\n' +
|
|
18
|
-
'
|
|
23
|
+
'/* The render size and the output size; then the frame jitter, in render texels. */\n' +
|
|
24
|
+
'@group(0) @binding(1) var<uniform> sizes: array<vec4<f32>, 2>;\n' +
|
|
19
25
|
'\n' +
|
|
20
26
|
'@vertex\n' +
|
|
21
27
|
'fn lateDepthVert(@builtin(vertex_index) index: u32) -> @builtin(position) vec4<f32> {\n' +
|
|
@@ -24,21 +30,40 @@ export const LATE_DEPTH_WGSL = '@group(0) @binding(0) var source: texture_depth_
|
|
|
24
30
|
' return vec4<f32>(x * 2.0 - 1.0, 1.0 - y * 2.0, 0.0, 1.0);\n' +
|
|
25
31
|
'}\n' +
|
|
26
32
|
'\n' +
|
|
33
|
+
'fn tap(base: vec2<i32>, x: i32, y: i32) -> f32 {\n' +
|
|
34
|
+
' let top = vec2<i32>(sizes[0].xy) - vec2<i32>(1);\n' +
|
|
35
|
+
' return textureLoad(source, clamp(base + vec2<i32>(x, y), vec2<i32>(0), top), 0);\n' +
|
|
36
|
+
'}\n' +
|
|
37
|
+
'\n' +
|
|
38
|
+
'/* The smaller of two differences, or none where they disagree in sign. */\n' +
|
|
39
|
+
'fn minmod(a: f32, b: f32) -> f32 {\n' +
|
|
40
|
+
' if (a * b <= 0.0) {\n' +
|
|
41
|
+
' return 0.0;\n' +
|
|
42
|
+
' }\n' +
|
|
43
|
+
' return select(b, a, abs(a) < abs(b));\n' +
|
|
44
|
+
'}\n' +
|
|
45
|
+
'\n' +
|
|
27
46
|
'@fragment\n' +
|
|
28
47
|
'fn lateDepthFrag(@builtin(position) at: vec4<f32>) -> @builtin(frag_depth) f32 {\n' +
|
|
29
|
-
'
|
|
48
|
+
' /* A texel stands at its index plus a half less the jitter, as the resolve places it. */\n' +
|
|
49
|
+
' let centre = at.xy * sizes[0].xy / sizes[0].zw - vec2<f32>(0.5) + sizes[1].xy;\n' +
|
|
30
50
|
' let base = vec2<i32>(floor(centre));\n' +
|
|
31
|
-
' let
|
|
32
|
-
' var
|
|
51
|
+
' let f = centre - floor(centre);\n' +
|
|
52
|
+
' var depth = ' +
|
|
33
53
|
FARTHEST +
|
|
34
54
|
';\n' +
|
|
35
|
-
' for (var
|
|
36
|
-
' for (var
|
|
37
|
-
' let
|
|
38
|
-
'
|
|
55
|
+
' for (var oy = 0; oy < 2; oy += 1) {\n' +
|
|
56
|
+
' for (var ox = 0; ox < 2; ox += 1) {\n' +
|
|
57
|
+
' let d = tap(base, ox, oy);\n' +
|
|
58
|
+
' let gx = minmod(tap(base, ox + 1, oy) - d, d - tap(base, ox - 1, oy));\n' +
|
|
59
|
+
' let gy = minmod(tap(base, ox, oy + 1) - d, d - tap(base, ox, oy - 1));\n' +
|
|
60
|
+
' let carried = d + gx * (f.x - f32(ox)) + gy * (f.y - f32(oy));\n' +
|
|
61
|
+
' depth = ' +
|
|
39
62
|
NEARER +
|
|
40
|
-
'(
|
|
63
|
+
'(depth, carried ' +
|
|
64
|
+
FARWARD +
|
|
65
|
+
' 0.25 * max(abs(gx), abs(gy)));\n' +
|
|
41
66
|
' }\n' +
|
|
42
67
|
' }\n' +
|
|
43
|
-
' return
|
|
68
|
+
' return clamp(depth, 0.0, 1.0);\n' +
|
|
44
69
|
'}\n';
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* `hasHistory` is a `u32` because a uniform buffer has no `bool`. The three matrices are the
|
|
5
5
|
* unjittered ones, in the same convention as the depths the accessors return.
|
|
6
6
|
*/
|
|
7
|
-
export declare const RECON_PARAMS_WGSL = "\nstruct ReconParams {\n renderSize: vec2<u32>,\n outputSize: vec2<u32>,\n jitter: vec2<f32>,\n previousJitter: vec2<f32>,\n inverseViewProj: mat4x4<f32>,\n previousViewProj: mat4x4<f32>,\n previousInverseViewProj: mat4x4<f32>,\n eye: vec4<f32>,\n previousEye: vec4<f32>,\n alpha: f32,\n sharpenAmount: f32,\n clampGamma: f32,\n hasHistory: u32,\n depthTolerance: f32,\n motionScale: f32,\n normalFloor: f32,\n normalCeiling: f32,\n}\n";
|
|
7
|
+
export declare const RECON_PARAMS_WGSL = "\nstruct ReconParams {\n renderSize: vec2<u32>,\n outputSize: vec2<u32>,\n jitter: vec2<f32>,\n previousJitter: vec2<f32>,\n inverseViewProj: mat4x4<f32>,\n previousViewProj: mat4x4<f32>,\n previousInverseViewProj: mat4x4<f32>,\n eye: vec4<f32>,\n previousEye: vec4<f32>,\n alpha: f32,\n sharpenAmount: f32,\n clampGamma: f32,\n hasHistory: u32,\n depthTolerance: f32,\n motionScale: f32,\n normalFloor: f32,\n normalCeiling: f32,\n periodStart: u32,\n antiFlicker: u32,\n flickerMemory: f32,\n flickerWidth: f32,\n reprojection: mat4x4<f32>,\n}\n";
|
|
8
8
|
/** Floats in `ReconParams`, which is what a caller sizes its uniform buffer by. */
|
|
9
|
-
export declare const RECON_PARAM_FLOATS =
|
|
9
|
+
export declare const RECON_PARAM_FLOATS = 92;
|
|
10
10
|
/** `SAMPLE_SPREAD` and `CONFIDENT_WEIGHT`, which the reference exports and this must not restate. */
|
|
11
11
|
export declare const RECON_SAMPLE_SPREAD = 0.47;
|
|
12
12
|
export declare const RECON_CONFIDENT_WEIGHT = 1;
|
|
@@ -23,18 +23,19 @@ export declare const RECON_WORKGROUP = 8;
|
|
|
23
23
|
*/
|
|
24
24
|
export declare const RECON_HISTORY_FORMAT: GPUTextureFormat;
|
|
25
25
|
/**
|
|
26
|
-
* The arithmetic, as text. Defines `reconResolvePixel(ox, oy) ->
|
|
27
|
-
* colour and the weight it has gathered — and `reconSharpenAt(ox, oy) -> vec3<f32>`, the picture
|
|
26
|
+
* The arithmetic, as text. Defines `reconResolvePixel(ox, oy) -> ReconResolved` — the next
|
|
27
|
+
* history's colour and the weight it has gathered, and the pixel's next flicker record — and `reconSharpenAt(ox, oy) -> vec3<f32>`, the picture
|
|
28
28
|
* shown, which reads the history the first has already written.
|
|
29
29
|
*/
|
|
30
|
-
export declare const RECON_RESOLVE_CORE_WGSL = "\nconst RECON_SAMPLE_SPREAD: f32 = 0.47;\nconst RECON_CONFIDENT_WEIGHT: f32 = 1.0;\nconst RECON_PLANAR_FROM: f32 = 0.25;\nconst RECON_PLANAR_TO: f32 = 0.5;\n\nfn reconClampTexel(value: i32, size: i32) -> i32 {\n return clamp(value, 0, size - 1);\n}\n\n/* JavaScript's Math.round, which is not WGSL's round: a half goes up, not to even. */\nfn reconRound(value: f32) -> f32 {\n return floor(value + 0.5);\n}\n\n/* Written out rather than the built-in, whose result is undefined where the edges are equal. */\nfn reconSmoothstep(edge0: f32, edge1: f32, x: f32) -> f32 {\n let t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);\n return t * t * (3.0 - 2.0 * t);\n}\n\nfn reconWeightAt(dx: f32, dy: f32) -> f32 {\n return exp(-(dx * dx + dy * dy) / (2.0 * RECON_SAMPLE_SPREAD * RECON_SAMPLE_SPREAD));\n}\n\nfn reconToYCoCg(c: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(\n c.r * 0.25 + c.g * 0.5 + c.b * 0.25,\n c.r * 0.5 - c.b * 0.5,\n -c.r * 0.25 + c.g * 0.5 - c.b * 0.25,\n );\n}\n\nfn reconFromYCoCg(c: vec3<f32>) -> vec3<f32> {\n let base = c.x - c.z;\n return vec3<f32>(base + c.y, c.x + c.z, base - c.y);\n}\n\nstruct ReconBox {\n low: vec3<f32>,\n high: vec3<f32>,\n}\n\n/*\n * Each channel's mean plus or minus gamma of its standard deviation \u2014 and a channel whose nine\n * samples all agree is that value exactly, because a mean of nine equal floats is not always one\n * of them and a box a rounding wide lets a history through by a rounding.\n */\nfn reconVarianceBox(samples: array<vec3<f32>, 9>, gamma: f32) -> ReconBox {\n var s = samples;\n var box: ReconBox;\n for (var c = 0u; c < 3u; c = c + 1u) {\n let first = s[0][c];\n var same = true;\n var sum = 0.0;\n for (var i = 0u; i < 9u; i = i + 1u) {\n let value = s[i][c];\n sum = sum + value;\n if (value != first) { same = false; }\n }\n if (same) {\n box.low[c] = first;\n box.high[c] = first;\n continue;\n }\n let mean = sum / 9.0;\n var spread = 0.0;\n for (var i = 0u; i < 9u; i = i + 1u) {\n let d = s[i][c] - mean;\n spread = spread + d * d;\n }\n let deviation = sqrt(spread / 9.0);\n box.low[c] = mean - gamma * deviation;\n box.high[c] = mean + gamma * deviation;\n }\n return box;\n}\n\n/*\n * The history pulled towards the box's centre until it is inside, by one ratio for all three\n * channels \u2014 a clamp per channel would land it on a corner and change its hue, which is coloured\n * fringing on every moving edge. A channel with no extent bounds anything that differs from it\n * infinitely, so such a history collapses onto the centre.\n */\nfn reconClipToBox(history: vec3<f32>, low: vec3<f32>, high: vec3<f32>) -> vec3<f32> {\n let centre = (low + high) * 0.5;\n var offset = history - centre;\n var extent = (high - low) * 0.5;\n var ratio = 0.0;\n var infinite = false;\n for (var c = 0u; c < 3u; c = c + 1u) {\n if (extent[c] > 1e-7) {\n ratio = max(ratio, abs(offset[c]) / extent[c]);\n } else if (abs(offset[c]) > 1e-7) {\n infinite = true;\n }\n }\n if (!infinite && !(ratio > 1.0)) { return history; }\n var scale = 0.0;\n if (!infinite) { scale = 1.0 / ratio; }\n return centre + offset * scale;\n}\n\nfn reconAccumulate(current: vec3<f32>, history: vec3<f32>, weight: f32, alpha: f32) -> vec3<f32> {\n let kept = clamp(weight, 0.0, 1.0) * (1.0 - clamp(alpha, 0.0, 1.0));\n return current * (1.0 - kept) + history * kept;\n}\n\nfn reconCatmullRom(t: f32) -> vec4<f32> {\n let t2 = t * t;\n let t3 = t2 * t;\n return vec4<f32>(\n -0.5 * t3 + t2 - 0.5 * t,\n 1.5 * t3 - 2.5 * t2 + 1.0,\n -1.5 * t3 + 2.0 * t2 + 0.5 * t,\n 0.5 * t3 - 0.5 * t2,\n );\n}\n\n/*\n * Five bilinear taps standing for the sixteen-texel Catmull-Rom: each axis's middle pair folded\n * into one tap placed between them, the corners dropped, the five weights renormalised. It is the\n * five-tap form because the taps are the expensive part \u2014 which is only true while the bilinear is\n * the sampler's, so the production module's accessor is a filtered sample and the check's is the\n * reference's own arithmetic over loaded texels.\n */\nstruct ReconTaps {\n at0: vec2<f32>,\n at1: vec2<f32>,\n at2: vec2<f32>,\n at3: vec2<f32>,\n at4: vec2<f32>,\n weights: array<f32, 5>,\n total: f32,\n}\n\nfn reconBicubicTaps(x: f32, y: f32) -> ReconTaps {\n let x1 = floor(x);\n let y1 = floor(y);\n let wx = reconCatmullRom(x - x1);\n let wy = reconCatmullRom(y - y1);\n let wx12 = wx[1] + wx[2];\n let wy12 = wy[1] + wy[2];\n let x12 = x1 + wx[2] / wx12;\n let y12 = y1 + wy[2] / wy12;\n var taps: ReconTaps;\n taps.at0 = vec2<f32>(x12, y1 - 1.0);\n taps.at1 = vec2<f32>(x1 - 1.0, y12);\n taps.at2 = vec2<f32>(x12, y12);\n taps.at3 = vec2<f32>(x1 + 2.0, y12);\n taps.at4 = vec2<f32>(x12, y1 + 2.0);\n taps.weights[0] = wx12 * wy[0];\n taps.weights[1] = wx[0] * wy12;\n taps.weights[2] = wx12 * wy12;\n taps.weights[3] = wx[3] * wy12;\n taps.weights[4] = wx12 * wy[3];\n taps.total =\n taps.weights[0] + taps.weights[1] + taps.weights[2] + taps.weights[3] + taps.weights[4];\n return taps;\n}\n\n/* A colour cannot be negative, and Catmull-Rom's negative lobes undershoot beside a bright edge. */\nfn reconSceneBicubic5(x: f32, y: f32) -> vec3<f32> {\n let taps = reconBicubicTaps(x, y);\n var sum = reconSceneBilinear(taps.at0) * taps.weights[0];\n sum = sum + reconSceneBilinear(taps.at1) * taps.weights[1];\n sum = sum + reconSceneBilinear(taps.at2) * taps.weights[2];\n sum = sum + reconSceneBilinear(taps.at3) * taps.weights[3];\n sum = sum + reconSceneBilinear(taps.at4) * taps.weights[4];\n return max(sum / taps.total, vec3<f32>(0.0));\n}\n\nfn reconHistoryBicubic5(x: f32, y: f32) -> vec4<f32> {\n let taps = reconBicubicTaps(x, y);\n var sum = reconHistoryBilinear(taps.at0) * taps.weights[0];\n sum = sum + reconHistoryBilinear(taps.at1) * taps.weights[1];\n sum = sum + reconHistoryBilinear(taps.at2) * taps.weights[2];\n sum = sum + reconHistoryBilinear(taps.at3) * taps.weights[3];\n sum = sum + reconHistoryBilinear(taps.at4) * taps.weights[4];\n return max(sum / taps.total, vec4<f32>(0.0));\n}\n\nstruct ReconWorld {\n ok: bool,\n position: vec3<f32>,\n}\n\n/* The world position a clip depth stands for, and nothing where the matrix has no answer there. */\nfn reconWorldFromDepth(m: mat4x4<f32>, u: f32, v: f32, clipDepth: f32) -> ReconWorld {\n var out: ReconWorld;\n out.position = vec3<f32>(0.0);\n out.ok = false;\n let x = u * 2.0 - 1.0;\n let y = v * 2.0 - 1.0;\n let w = m[0][3] * x + m[1][3] * y + m[2][3] * clipDepth + m[3][3];\n if (!(abs(w) > 1e-12)) { return out; }\n let p = m * vec4<f32>(x, y, clipDepth, 1.0);\n out.position = p.xyz / w;\n out.ok = all(abs(out.position) < vec3<f32>(3.4e38));\n return out;\n}\n\nstruct ReconNormal {\n ok: bool,\n normal: vec3<f32>,\n}\n\n/* Turned to face the eye, so the answer is the same whichever way the target's rows run. */\nfn reconNormalFrom(\n centre: vec3<f32>,\n right: vec3<f32>,\n up: vec3<f32>,\n eye: vec3<f32>,\n) -> ReconNormal {\n var out: ReconNormal;\n out.normal = vec3<f32>(0.0);\n out.ok = false;\n let a = right - centre;\n let b = up - centre;\n let n = cross(a, b);\n let length2 = dot(n, n);\n let scale2 = dot(a, a) * dot(b, b);\n if (!(length2 > 1e-12 * scale2)) { return out; }\n let toEye = dot(n, eye - centre);\n var sign = 1.0;\n if (toEye < 0.0) { sign = -1.0; }\n out.normal = n * (sign / sqrt(length2));\n out.ok = true;\n return out;\n}\n\nfn reconDisocclusion(\n currDepth: f32,\n histDepth: f32,\n motionLength: f32,\n normalDot: f32,\n slope: f32,\n) -> f32 {\n if (!(currDepth > 0.0) || !(histDepth > 0.0) || !(motionLength >= 0.0)) { return 0.0; }\n let disagreement = abs(currDepth - histDepth) / currDepth;\n let tolerance = recon.depthTolerance + recon.motionScale * motionLength + slope;\n let depth = 1.0 - reconSmoothstep(tolerance, 2.0 * tolerance, disagreement);\n let normal = reconSmoothstep(recon.normalFloor, recon.normalCeiling, normalDot);\n return depth * normal;\n}\n\nstruct ReconAt {\n depth: f32,\n position: vec3<f32>,\n}\n\n/* A texel's world position at its unjittered uv, and the view depth it stands at, or zero. */\nfn reconWorldAt(previous: bool, x: i32, y: i32) -> ReconAt {\n let w = i32(recon.renderSize.x);\n let h = i32(recon.renderSize.y);\n let tx = reconClampTexel(x, w);\n let ty = reconClampTexel(y, h);\n var jitter = recon.jitter;\n var m = recon.inverseViewProj;\n var z = reconDepth(tx, ty);\n if (previous) {\n jitter = recon.previousJitter;\n m = recon.previousInverseViewProj;\n z = reconPreviousDepth(tx, ty);\n }\n let u = (f32(tx) + 0.5 - jitter.x) / f32(w);\n let v = (f32(ty) + 0.5 - jitter.y) / f32(h);\n var out: ReconAt;\n out.depth = 0.0;\n out.position = vec3<f32>(0.0);\n let world = reconWorldFromDepth(m, u, v, z);\n if (!world.ok) { return out; }\n out.position = world.position;\n /* The view depth is the clip w, which the inverse's w is the reciprocal of. */\n let cw = m[0][3] * (u * 2.0 - 1.0) + m[1][3] * (v * 2.0 - 1.0) + m[2][3] * z + m[3][3];\n out.depth = 1.0 / cw;\n return out;\n}\n\n/* The neighbour on the inside of the border, so the edge texels have a normal too. */\nfn reconNormalAt(previous: bool, x: i32, y: i32) -> ReconNormal {\n var out: ReconNormal;\n out.normal = vec3<f32>(0.0);\n out.ok = false;\n let w = i32(recon.renderSize.x);\n let h = i32(recon.renderSize.y);\n let centre = reconWorldAt(previous, x, y);\n if (!(centre.depth > 0.0)) { return out; }\n var dx = -1;\n if (x + 1 < w) { dx = 1; }\n var dy = -1;\n if (y + 1 < h) { dy = 1; }\n let right = reconWorldAt(previous, x + dx, y);\n if (!(right.depth > 0.0)) { return out; }\n let up = reconWorldAt(previous, x, y + dy);\n if (!(up.depth > 0.0)) { return out; }\n var eye = recon.eye.xyz;\n if (previous) { eye = recon.previousEye.xyz; }\n return reconNormalFrom(centre.position, right.position, up.position, eye);\n}\n\n/* resolve.ts's viewDepthAt. */\nfn reconViewDepthAt(previous: bool, x: i32, y: i32) -> f32 {\n let w = i32(recon.renderSize.x);\n let h = i32(recon.renderSize.y);\n if (x < 0 || y < 0 || x >= w || y >= h) { return 0.0; }\n var jitter = recon.jitter;\n var m = recon.inverseViewProj;\n var z = 0.0;\n if (previous) {\n jitter = recon.previousJitter;\n m = recon.previousInverseViewProj;\n z = reconPreviousDepth(x, y);\n } else {\n z = reconDepth(x, y);\n }\n let u = (f32(x) + 0.5 - jitter.x) / f32(w);\n let v = (f32(y) + 0.5 - jitter.y) / f32(h);\n let cw = m[0][3] * (u * 2.0 - 1.0) + m[1][3] * (v * 2.0 - 1.0) + m[2][3] * z + m[3][3];\n if (!(abs(cw) > 1e-12)) { return 0.0; }\n return 1.0 / cw;\n}\n\n/* disocclusion.ts's planarity. */\nfn reconPlanarity(before: f32, centre: f32, after: f32) -> f32 {\n if (!(before > 0.0) || !(centre > 0.0) || !(after > 0.0)) { return 1.0; }\n let a = 1.0 / after - 1.0 / centre;\n let b = 1.0 / before - 1.0 / centre;\n let spread = abs(a) + abs(b);\n if (!(spread > 0.0)) { return 1.0; }\n return 1.0 - reconSmoothstep(RECON_PLANAR_FROM, RECON_PLANAR_TO, abs(a + b) / spread);\n}\n\n/* disocclusion.ts's surfaceSlope. */\nfn reconSurfaceSlope(before: f32, centre: f32, after: f32) -> f32 {\n let hasAfter = after > 0.0;\n let hasBefore = before > 0.0;\n if (!hasAfter) {\n if (!hasBefore) { return 0.0; }\n return abs(before - centre) / centre;\n }\n if (!hasBefore) { return abs(after - centre) / centre; }\n let a = after - centre;\n let b = before - centre;\n if (a * b > 0.0) { return 0.0; }\n return min(abs(a), abs(b)) / centre;\n}\n\nstruct ReconSurface {\n planar: f32,\n slope: f32,\n}\n\n/* resolve.ts's surfaceAt. */\nfn reconSurfaceAt(previous: bool, x: i32, y: i32, centre: f32) -> ReconSurface {\n var out: ReconSurface;\n out.planar = 1.0;\n out.slope = 0.0;\n for (var axis = 0; axis < 2; axis = axis + 1) {\n let ax = 1 - axis;\n let ay = axis;\n let after = reconViewDepthAt(previous, x + ax, y + ay);\n let before = reconViewDepthAt(previous, x - ax, y - ay);\n out.planar = out.planar * reconPlanarity(before, centre, after);\n out.slope = max(out.slope, reconSurfaceSlope(before, centre, after));\n }\n return out;\n}\n\nstruct ReconHistory {\n weight: f32,\n colour: vec4<f32>,\n}\n\n/*\n * The weight a pixel's history still deserves: none on the first frame, none where the surface was\n * behind last frame's eye or off its picture, and otherwise what it gathered, scaled by whether it\n * is the same surface.\n */\nfn reconHistoryWeight(u: f32, v: f32, dx: i32, dy: i32) -> ReconHistory {\n var out: ReconHistory;\n out.weight = 0.0;\n out.colour = vec4<f32>(0.0);\n if (recon.hasHistory == 0u) { return out; }\n let rw = f32(recon.renderSize.x);\n let rh = f32(recon.renderSize.y);\n let motion = reconMotion(dx, dy);\n var mu = 0.0;\n var mv = 0.0;\n var expected = 0.0;\n if (motion.w > 0.5) {\n mu = motion.x;\n mv = motion.y;\n expected = motion.z;\n } else {\n let here = reconWorldAt(false, dx, dy);\n if (!(here.depth > 0.0)) { return out; }\n let clip = recon.previousViewProj * vec4<f32>(here.position, 1.0);\n /*\n * A surface behind last frame's eye has a w that is not positive: the disocclusion trusts no\n * such depth, so it needs no refusal of its own here.\n */\n expected = clip.w;\n let du = (f32(dx) + 0.5 - recon.jitter.x) / rw;\n let dv = (f32(dy) + 0.5 - recon.jitter.y) / rh;\n mu = (clip.x / expected) * 0.5 + 0.5 - du;\n mv = (clip.y / expected) * 0.5 + 0.5 - dv;\n }\n\n let pu = u + mu;\n let pv = v + mv;\n if (!(pu >= 0.0 && pu <= 1.0 && pv >= 0.0 && pv <= 1.0)) { return out; }\n out.colour = reconHistoryBicubic5(\n pu * f32(recon.outputSize.x) - 0.5,\n pv * f32(recon.outputSize.y) - 0.5,\n );\n /* Last frame's depth, searched around where the dilated texel was: see resolve.ts. */\n let su = (f32(dx) + 0.5 - recon.jitter.x) / rw + mu;\n let sv = (f32(dy) + 0.5 - recon.jitter.y) / rh + mv;\n let cx = reconClampTexel(i32(reconRound(su * rw + recon.previousJitter.x - 0.5)), i32(rw));\n let cy = reconClampTexel(i32(reconRound(sv * rh + recon.previousJitter.y - 0.5)), i32(rh));\n var held = reconViewDepthAt(true, cx, cy);\n var px = cx;\n var py = cy;\n if (!(held > 0.0 && abs(held - expected) <= recon.depthTolerance * expected)) {\n held = 0.0;\n var nearest = 3.4e38;\n for (var j = -1; j <= 1; j = j + 1) {\n for (var i = -1; i <= 1; i = i + 1) {\n let tx = reconClampTexel(cx + i, i32(rw));\n let ty = reconClampTexel(cy + j, i32(rh));\n let depth = reconViewDepthAt(true, tx, ty);\n if (!(depth > 0.0)) { continue; }\n let off = abs(depth - expected);\n if (off < nearest) {\n nearest = off;\n held = depth;\n px = tx;\n py = ty;\n }\n }\n }\n }\n\n let here = reconSurfaceAt(false, dx, dy, reconViewDepthAt(false, dx, dy));\n var planar = here.planar;\n if (planar > 0.0) { planar = planar * reconSurfaceAt(true, px, py, held).planar; }\n var normalDot = 1.0;\n if (planar > 0.0) {\n let hereNormal = reconNormalAt(false, dx, dy);\n let thereNormal = reconNormalAt(true, px, py);\n if (hereNormal.ok && thereNormal.ok) {\n normalDot = 1.0 - planar * (1.0 - dot(hereNormal.normal, thereNormal.normal));\n }\n }\n let trust = reconDisocclusion(expected, held, length(vec2<f32>(mu, mv)), normalDot, here.slope);\n out.weight = out.colour.w * trust;\n return out;\n}\n\n/* One output pixel: the history's next colour, before sharpening, and the weight it has gathered. */\nfn reconResolvePixel(ox: i32, oy: i32) -> vec4<f32> {\n let rw = i32(recon.renderSize.x);\n let rh = i32(recon.renderSize.y);\n let ow = i32(recon.outputSize.x);\n let oh = i32(recon.outputSize.y);\n let u = (f32(ox) + 0.5) / f32(ow);\n let v = (f32(oy) + 0.5) / f32(oh);\n let jx = recon.jitter.x;\n let jy = recon.jitter.y;\n\n /* Where this frame observed the pixel, and the render read there for the gaps. */\n let rx = u * f32(rw) + jx - 0.5;\n let ry = v * f32(rh) + jy - 0.5;\n let sample = reconSceneBicubic5(rx, ry);\n let nx = reconClampTexel(i32(reconRound(rx)), rw);\n let ny = reconClampTexel(i32(reconRound(ry)), rh);\n\n /* Each texel around: its weight, its colour in the box, and its depth. */\n var nearest = reconDepth(nx, ny);\n var dx = nx;\n var dy = ny;\n var gathered = 0.0;\n var accum = vec3<f32>(0.0);\n var neighbours: array<vec3<f32>, 9>;\n for (var j = -1; j <= 1; j = j + 1) {\n for (var i = -1; i <= 1; i = i + 1) {\n let tx = reconClampTexel(nx + i, rw);\n let ty = reconClampTexel(ny + j, rh);\n let colour = reconScene(tx, ty);\n let weight = reconWeightAt(\n ((f32(tx) + 0.5 - jx) / f32(rw)) * f32(ow) - (f32(ox) + 0.5),\n ((f32(ty) + 0.5 - jy) / f32(rh)) * f32(oh) - (f32(oy) + 0.5),\n );\n gathered = gathered + weight;\n accum = accum + colour * weight;\n neighbours[(j + 1) * 3 + (i + 1)] = reconToYCoCg(colour);\n let z = reconDepth(tx, ty);\n if (z < nearest) {\n nearest = z;\n dx = tx;\n dy = ty;\n }\n }\n }\n let box = reconVarianceBox(neighbours, recon.clampGamma);\n accum = accum / gathered;\n\n /* The history, and the weight it still deserves; a tenth of each frame is always new. */\n let cap = (1.0 - recon.alpha) / recon.alpha;\n let history = reconHistoryWeight(u, v, dx, dy);\n let kept = min(cap, history.weight);\n\n let total = kept + gathered;\n var mixed = accum;\n if (kept > 0.0) {\n let clipped = reconClipToBox(reconToYCoCg(history.colour.xyz), box.low, box.high);\n mixed = reconAccumulate(accum, reconFromYCoCg(clipped), 1.0, gathered / total);\n }\n let known = min(1.0, total / RECON_CONFIDENT_WEIGHT);\n return vec4<f32>(sample * (1.0 - known) + mixed * known, total);\n}\n\n/*\n * The centre pushed away from its four neighbours' mean, and held inside the range of the five \u2014\n * the halo a plain unsharp mask draws beside every edge is a value outside that range.\n */\nfn reconSharpenAt(ox: i32, oy: i32) -> vec3<f32> {\n let ow = i32(recon.outputSize.x);\n let oh = i32(recon.outputSize.y);\n let centre = reconHistory(reconClampTexel(ox, ow), reconClampTexel(oy, oh)).xyz;\n var offsets = array<vec2<i32>, 4>(\n vec2<i32>(-1, 0),\n vec2<i32>(1, 0),\n vec2<i32>(0, -1),\n vec2<i32>(0, 1),\n );\n var low = centre;\n var high = centre;\n var sum = vec3<f32>(0.0);\n for (var n = 0; n < 4; n = n + 1) {\n let at = offsets[n];\n let value = reconHistory(\n reconClampTexel(ox + at.x, ow),\n reconClampTexel(oy + at.y, oh),\n ).xyz;\n sum = sum + value;\n low = min(low, value);\n high = max(high, value);\n }\n let pushed = centre + recon.sharpenAmount * (centre - sum / 4.0);\n return min(high, max(low, pushed));\n}\n";
|
|
30
|
+
export declare const RECON_RESOLVE_CORE_WGSL = "\nconst RECON_SAMPLE_SPREAD: f32 = 0.47;\nconst RECON_CONFIDENT_WEIGHT: f32 = 1.0;\nconst RECON_PLANAR_FROM: f32 = 0.25;\nconst RECON_PLANAR_TO: f32 = 0.5;\nconst RECON_FLICKER_BLEND: f32 = 0.97;\nconst RECON_FLICKER_REPEAT: f32 = 0.05;\nconst RECON_STILL_FROM: f32 = 0.01;\nconst RECON_STILL_TO: f32 = 0.05;\nconst RECON_DEPTH_SWING_WIDTH: f32 = 3.0;\n\nfn reconClampTexel(value: i32, size: i32) -> i32 {\n return clamp(value, 0, size - 1);\n}\n\n/* JavaScript's Math.round, which is not WGSL's round: a half goes up, not to even. */\nfn reconRound(value: f32) -> f32 {\n return floor(value + 0.5);\n}\n\n/* Written out rather than the built-in, whose result is undefined where the edges are equal. */\nfn reconSmoothstep(edge0: f32, edge1: f32, x: f32) -> f32 {\n let t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);\n return t * t * (3.0 - 2.0 * t);\n}\n\nfn reconWeightAt(dx: f32, dy: f32) -> f32 {\n return exp(-(dx * dx + dy * dy) / (2.0 * RECON_SAMPLE_SPREAD * RECON_SAMPLE_SPREAD));\n}\n\nfn reconToYCoCg(c: vec3<f32>) -> vec3<f32> {\n return vec3<f32>(\n c.r * 0.25 + c.g * 0.5 + c.b * 0.25,\n c.r * 0.5 - c.b * 0.5,\n -c.r * 0.25 + c.g * 0.5 - c.b * 0.25,\n );\n}\n\nfn reconFromYCoCg(c: vec3<f32>) -> vec3<f32> {\n let base = c.x - c.z;\n return vec3<f32>(base + c.y, c.x + c.z, base - c.y);\n}\n\nstruct ReconBox {\n low: vec3<f32>,\n high: vec3<f32>,\n}\n\n/*\n * Each channel's mean plus or minus gamma of its standard deviation \u2014 and a channel whose nine\n * samples all agree is that value exactly, because a mean of nine equal floats is not always one\n * of them and a box a rounding wide lets a history through by a rounding.\n */\nfn reconVarianceBox(samples: array<vec3<f32>, 9>, gamma: f32) -> ReconBox {\n var s = samples;\n var box: ReconBox;\n for (var c = 0u; c < 3u; c = c + 1u) {\n let first = s[0][c];\n var same = true;\n var sum = 0.0;\n for (var i = 0u; i < 9u; i = i + 1u) {\n let value = s[i][c];\n sum = sum + value;\n if (value != first) { same = false; }\n }\n if (same) {\n box.low[c] = first;\n box.high[c] = first;\n continue;\n }\n let mean = sum / 9.0;\n var spread = 0.0;\n for (var i = 0u; i < 9u; i = i + 1u) {\n let d = s[i][c] - mean;\n spread = spread + d * d;\n }\n let deviation = sqrt(spread / 9.0);\n box.low[c] = mean - gamma * deviation;\n box.high[c] = mean + gamma * deviation;\n }\n return box;\n}\n\n/*\n * The history pulled towards the box's centre until it is inside, by one ratio for all three\n * channels \u2014 a clamp per channel would land it on a corner and change its hue, which is coloured\n * fringing on every moving edge. A channel with no extent bounds anything that differs from it\n * infinitely, so such a history collapses onto the centre.\n */\nfn reconClipToBox(history: vec3<f32>, low: vec3<f32>, high: vec3<f32>) -> vec3<f32> {\n let centre = (low + high) * 0.5;\n var offset = history - centre;\n var extent = (high - low) * 0.5;\n var ratio = 0.0;\n var infinite = false;\n for (var c = 0u; c < 3u; c = c + 1u) {\n if (extent[c] > 1e-7) {\n ratio = max(ratio, abs(offset[c]) / extent[c]);\n } else if (abs(offset[c]) > 1e-7) {\n infinite = true;\n }\n }\n if (!infinite && !(ratio > 1.0)) { return history; }\n var scale = 0.0;\n if (!infinite) { scale = 1.0 / ratio; }\n return centre + offset * scale;\n}\n\nfn reconAccumulate(current: vec3<f32>, history: vec3<f32>, weight: f32, alpha: f32) -> vec3<f32> {\n let kept = clamp(weight, 0.0, 1.0) * (1.0 - clamp(alpha, 0.0, 1.0));\n return current * (1.0 - kept) + history * kept;\n}\n\nfn reconCatmullRom(t: f32) -> vec4<f32> {\n let t2 = t * t;\n let t3 = t2 * t;\n return vec4<f32>(\n -0.5 * t3 + t2 - 0.5 * t,\n 1.5 * t3 - 2.5 * t2 + 1.0,\n -1.5 * t3 + 2.0 * t2 + 0.5 * t,\n 0.5 * t3 - 0.5 * t2,\n );\n}\n\n/*\n * Five bilinear taps standing for the sixteen-texel Catmull-Rom: each axis's middle pair folded\n * into one tap placed between them, the corners dropped, the five weights renormalised. It is the\n * five-tap form because the taps are the expensive part \u2014 which is only true while the bilinear is\n * the sampler's, so the production module's accessor is a filtered sample and the check's is the\n * reference's own arithmetic over loaded texels.\n */\nstruct ReconTaps {\n at0: vec2<f32>,\n at1: vec2<f32>,\n at2: vec2<f32>,\n at3: vec2<f32>,\n at4: vec2<f32>,\n weights: array<f32, 5>,\n total: f32,\n}\n\nfn reconBicubicTaps(x: f32, y: f32) -> ReconTaps {\n let x1 = floor(x);\n let y1 = floor(y);\n let wx = reconCatmullRom(x - x1);\n let wy = reconCatmullRom(y - y1);\n let wx12 = wx[1] + wx[2];\n let wy12 = wy[1] + wy[2];\n let x12 = x1 + wx[2] / wx12;\n let y12 = y1 + wy[2] / wy12;\n var taps: ReconTaps;\n taps.at0 = vec2<f32>(x12, y1 - 1.0);\n taps.at1 = vec2<f32>(x1 - 1.0, y12);\n taps.at2 = vec2<f32>(x12, y12);\n taps.at3 = vec2<f32>(x1 + 2.0, y12);\n taps.at4 = vec2<f32>(x12, y1 + 2.0);\n taps.weights[0] = wx12 * wy[0];\n taps.weights[1] = wx[0] * wy12;\n taps.weights[2] = wx12 * wy12;\n taps.weights[3] = wx[3] * wy12;\n taps.weights[4] = wx12 * wy[3];\n taps.total =\n taps.weights[0] + taps.weights[1] + taps.weights[2] + taps.weights[3] + taps.weights[4];\n return taps;\n}\n\n/* A colour cannot be negative, and Catmull-Rom's negative lobes undershoot beside a bright edge. */\nfn reconSceneBicubic5(x: f32, y: f32) -> vec3<f32> {\n let taps = reconBicubicTaps(x, y);\n var sum = reconSceneBilinear(taps.at0) * taps.weights[0];\n sum = sum + reconSceneBilinear(taps.at1) * taps.weights[1];\n sum = sum + reconSceneBilinear(taps.at2) * taps.weights[2];\n sum = sum + reconSceneBilinear(taps.at3) * taps.weights[3];\n sum = sum + reconSceneBilinear(taps.at4) * taps.weights[4];\n return max(sum / taps.total, vec3<f32>(0.0));\n}\n\nfn reconHistoryBicubic5(x: f32, y: f32) -> vec4<f32> {\n let taps = reconBicubicTaps(x, y);\n var sum = reconHistoryBilinear(taps.at0) * taps.weights[0];\n sum = sum + reconHistoryBilinear(taps.at1) * taps.weights[1];\n sum = sum + reconHistoryBilinear(taps.at2) * taps.weights[2];\n sum = sum + reconHistoryBilinear(taps.at3) * taps.weights[3];\n sum = sum + reconHistoryBilinear(taps.at4) * taps.weights[4];\n return max(sum / taps.total, vec4<f32>(0.0));\n}\n\nstruct ReconWorld {\n ok: bool,\n position: vec3<f32>,\n}\n\n/* The world position a clip depth stands for, and nothing where the matrix has no answer there. */\nfn reconWorldFromDepth(m: mat4x4<f32>, u: f32, v: f32, clipDepth: f32) -> ReconWorld {\n var out: ReconWorld;\n out.position = vec3<f32>(0.0);\n out.ok = false;\n let x = u * 2.0 - 1.0;\n let y = v * 2.0 - 1.0;\n let w = m[0][3] * x + m[1][3] * y + m[2][3] * clipDepth + m[3][3];\n if (!(abs(w) > 1e-12)) { return out; }\n let p = m * vec4<f32>(x, y, clipDepth, 1.0);\n out.position = p.xyz / w;\n out.ok = all(abs(out.position) < vec3<f32>(3.4e38));\n return out;\n}\n\nstruct ReconNormal {\n ok: bool,\n normal: vec3<f32>,\n}\n\n/* Turned to face the eye, so the answer is the same whichever way the target's rows run. */\nfn reconNormalFrom(\n centre: vec3<f32>,\n right: vec3<f32>,\n up: vec3<f32>,\n eye: vec3<f32>,\n) -> ReconNormal {\n var out: ReconNormal;\n out.normal = vec3<f32>(0.0);\n out.ok = false;\n let a = right - centre;\n let b = up - centre;\n let n = cross(a, b);\n let length2 = dot(n, n);\n let scale2 = dot(a, a) * dot(b, b);\n if (!(length2 > 1e-12 * scale2)) { return out; }\n let toEye = dot(n, eye - centre);\n var sign = 1.0;\n if (toEye < 0.0) { sign = -1.0; }\n out.normal = n * (sign / sqrt(length2));\n out.ok = true;\n return out;\n}\n\nfn reconDisocclusion(\n currDepth: f32,\n histDepth: f32,\n motionLength: f32,\n normalDot: f32,\n slope: f32,\n) -> f32 {\n if (!(currDepth > 0.0) || !(histDepth > 0.0) || !(motionLength >= 0.0)) { return 0.0; }\n let disagreement = abs(currDepth - histDepth) / currDepth;\n let tolerance = recon.depthTolerance + recon.motionScale * motionLength + slope;\n let depth = 1.0 - reconSmoothstep(tolerance, 2.0 * tolerance, disagreement);\n let normal = reconSmoothstep(recon.normalFloor, recon.normalCeiling, normalDot);\n return depth * normal;\n}\n\nstruct ReconAt {\n depth: f32,\n position: vec3<f32>,\n}\n\n/* A texel's world position at its unjittered uv, and the view depth it stands at, or zero. */\nfn reconWorldAt(previous: bool, x: i32, y: i32) -> ReconAt {\n let w = i32(recon.renderSize.x);\n let h = i32(recon.renderSize.y);\n let tx = reconClampTexel(x, w);\n let ty = reconClampTexel(y, h);\n var jitter = recon.jitter;\n var m = recon.inverseViewProj;\n var z = reconDepth(tx, ty);\n if (previous) {\n jitter = recon.previousJitter;\n m = recon.previousInverseViewProj;\n z = reconPreviousDepth(tx, ty);\n }\n let u = (f32(tx) + 0.5 - jitter.x) / f32(w);\n let v = (f32(ty) + 0.5 - jitter.y) / f32(h);\n var out: ReconAt;\n out.depth = 0.0;\n out.position = vec3<f32>(0.0);\n let world = reconWorldFromDepth(m, u, v, z);\n if (!world.ok) { return out; }\n out.position = world.position;\n /* The view depth is the clip w, which the inverse's w is the reciprocal of. */\n let cw = m[0][3] * (u * 2.0 - 1.0) + m[1][3] * (v * 2.0 - 1.0) + m[2][3] * z + m[3][3];\n out.depth = 1.0 / cw;\n return out;\n}\n\n/* The neighbour on the inside of the border, so the edge texels have a normal too. */\nfn reconNormalAt(previous: bool, x: i32, y: i32) -> ReconNormal {\n var out: ReconNormal;\n out.normal = vec3<f32>(0.0);\n out.ok = false;\n let w = i32(recon.renderSize.x);\n let h = i32(recon.renderSize.y);\n let centre = reconWorldAt(previous, x, y);\n if (!(centre.depth > 0.0)) { return out; }\n var dx = -1;\n if (x + 1 < w) { dx = 1; }\n var dy = -1;\n if (y + 1 < h) { dy = 1; }\n let right = reconWorldAt(previous, x + dx, y);\n if (!(right.depth > 0.0)) { return out; }\n let up = reconWorldAt(previous, x, y + dy);\n if (!(up.depth > 0.0)) { return out; }\n var eye = recon.eye.xyz;\n if (previous) { eye = recon.previousEye.xyz; }\n return reconNormalFrom(centre.position, right.position, up.position, eye);\n}\n\n/* resolve.ts's viewDepthAt. */\nfn reconViewDepthAt(previous: bool, x: i32, y: i32) -> f32 {\n let w = i32(recon.renderSize.x);\n let h = i32(recon.renderSize.y);\n if (x < 0 || y < 0 || x >= w || y >= h) { return 0.0; }\n var jitter = recon.jitter;\n var m = recon.inverseViewProj;\n var z = 0.0;\n if (previous) {\n jitter = recon.previousJitter;\n m = recon.previousInverseViewProj;\n z = reconPreviousDepth(x, y);\n } else {\n z = reconDepth(x, y);\n }\n let u = (f32(x) + 0.5 - jitter.x) / f32(w);\n let v = (f32(y) + 0.5 - jitter.y) / f32(h);\n let cw = m[0][3] * (u * 2.0 - 1.0) + m[1][3] * (v * 2.0 - 1.0) + m[2][3] * z + m[3][3];\n if (!(abs(cw) > 1e-12)) { return 0.0; }\n return 1.0 / cw;\n}\n\n/* disocclusion.ts's planarity. */\nfn reconPlanarity(before: f32, centre: f32, after: f32) -> f32 {\n if (!(before > 0.0) || !(centre > 0.0) || !(after > 0.0)) { return 1.0; }\n let a = 1.0 / after - 1.0 / centre;\n let b = 1.0 / before - 1.0 / centre;\n let spread = abs(a) + abs(b);\n if (!(spread > 0.0)) { return 1.0; }\n return 1.0 - reconSmoothstep(RECON_PLANAR_FROM, RECON_PLANAR_TO, abs(a + b) / spread);\n}\n\n/* disocclusion.ts's surfaceSlope. */\nfn reconSurfaceSlope(before: f32, centre: f32, after: f32) -> f32 {\n let hasAfter = after > 0.0;\n let hasBefore = before > 0.0;\n if (!hasAfter) {\n if (!hasBefore) { return 0.0; }\n return abs(before - centre) / centre;\n }\n if (!hasBefore) { return abs(after - centre) / centre; }\n let a = after - centre;\n let b = before - centre;\n if (a * b > 0.0) { return 0.0; }\n return min(abs(a), abs(b)) / centre;\n}\n\nstruct ReconSurface {\n planar: f32,\n slope: f32,\n}\n\n/* resolve.ts's surfaceAt. */\nfn reconSurfaceAt(previous: bool, x: i32, y: i32, centre: f32) -> ReconSurface {\n var out: ReconSurface;\n out.planar = 1.0;\n out.slope = 0.0;\n for (var axis = 0; axis < 2; axis = axis + 1) {\n let ax = 1 - axis;\n let ay = axis;\n let after = reconViewDepthAt(previous, x + ax, y + ay);\n let before = reconViewDepthAt(previous, x - ax, y - ay);\n out.planar = out.planar * reconPlanarity(before, centre, after);\n out.slope = max(out.slope, reconSurfaceSlope(before, centre, after));\n }\n return out;\n}\n\nstruct ReconHistory {\n weight: f32,\n colour: vec4<f32>,\n /* How far the surface moved, in output pixels; read only where the weight is not zero. */\n moved: f32,\n /* How far, relative, last frame's depth missed the one expected there; -1 where none was held. */\n missed: f32,\n}\n\n/*\n * The weight a pixel's history still deserves: none on the first frame, none where the surface was\n * behind last frame's eye or off its picture, and otherwise what it gathered, scaled by whether it\n * is the same surface.\n */\nfn reconHistoryWeight(u: f32, v: f32, dx: i32, dy: i32, swing: f32) -> ReconHistory {\n var out: ReconHistory;\n out.weight = 0.0;\n out.colour = vec4<f32>(0.0);\n out.moved = 0.0;\n out.missed = -1.0;\n if (recon.hasHistory == 0u) { return out; }\n let rw = f32(recon.renderSize.x);\n let rh = f32(recon.renderSize.y);\n let motion = reconMotion(dx, dy);\n var mu = 0.0;\n var mv = 0.0;\n var expected = 0.0;\n if (motion.w > 0.5) {\n mu = motion.x;\n mv = motion.y;\n expected = motion.z;\n } else {\n /* Through the one reprojection matrix the renderer multiplied: see resolve.ts. */\n let du = (f32(dx) + 0.5 - recon.jitter.x) / rw;\n let dv = (f32(dy) + 0.5 - recon.jitter.y) / rh;\n let ndc = vec4<f32>(du * 2.0 - 1.0, dv * 2.0 - 1.0, reconDepth(dx, dy), 1.0);\n let m = recon.inverseViewProj;\n let hw = m[0][3] * ndc.x + m[1][3] * ndc.y + m[2][3] * ndc.z + m[3][3];\n if (!(hw > 1e-12)) { return out; }\n let clip = recon.reprojection * ndc;\n /*\n * A surface behind last frame's eye has a w that is not positive: the disocclusion trusts no\n * such depth, so it needs no refusal of its own here.\n */\n expected = clip.w / hw;\n mu = (clip.x / clip.w) * 0.5 + 0.5 - du;\n mv = (clip.y / clip.w) * 0.5 + 0.5 - dv;\n }\n\n out.moved = length(vec2<f32>(mu * f32(recon.outputSize.x), mv * f32(recon.outputSize.y)));\n let pu = u + mu;\n let pv = v + mv;\n if (!(pu >= 0.0 && pu <= 1.0 && pv >= 0.0 && pv <= 1.0)) { return out; }\n out.colour = reconHistoryBicubic5(\n pu * f32(recon.outputSize.x) - 0.5,\n pv * f32(recon.outputSize.y) - 0.5,\n );\n /* Last frame's depth, searched around where the dilated texel was: see resolve.ts. */\n let su = (f32(dx) + 0.5 - recon.jitter.x) / rw + mu;\n let sv = (f32(dy) + 0.5 - recon.jitter.y) / rh + mv;\n let cx = reconClampTexel(i32(reconRound(su * rw + recon.previousJitter.x - 0.5)), i32(rw));\n let cy = reconClampTexel(i32(reconRound(sv * rh + recon.previousJitter.y - 0.5)), i32(rh));\n var held = reconViewDepthAt(true, cx, cy);\n var px = cx;\n var py = cy;\n if (!(held > 0.0 && abs(held - expected) <= recon.depthTolerance * expected)) {\n held = 0.0;\n var nearest = 3.4e38;\n for (var j = -1; j <= 1; j = j + 1) {\n for (var i = -1; i <= 1; i = i + 1) {\n let tx = reconClampTexel(cx + i, i32(rw));\n let ty = reconClampTexel(cy + j, i32(rh));\n let depth = reconViewDepthAt(true, tx, ty);\n if (!(depth > 0.0)) { continue; }\n let off = abs(depth - expected);\n if (off < nearest) {\n nearest = off;\n held = depth;\n px = tx;\n py = ty;\n }\n }\n }\n }\n\n let here = reconSurfaceAt(false, dx, dy, reconViewDepthAt(false, dx, dy));\n var planar = here.planar;\n if (planar > 0.0) { planar = planar * reconSurfaceAt(true, px, py, held).planar; }\n var normalDot = 1.0;\n if (planar > 0.0) {\n let hereNormal = reconNormalAt(false, dx, dy);\n let thereNormal = reconNormalAt(true, px, py);\n if (hereNormal.ok && thereNormal.ok) {\n normalDot = 1.0 - planar * (1.0 - dot(hereNormal.normal, thereNormal.normal));\n }\n }\n if (held > 0.0 && expected > 0.0) { out.missed = abs(held - expected) / expected; }\n /* A still pixel's own held depth swing: see resolve.ts. */\n var swung = 0.0;\n if (swing > 0.0) {\n swung = RECON_DEPTH_SWING_WIDTH * swing *\n (1.0 - reconSmoothstep(RECON_STILL_FROM, RECON_STILL_TO, out.moved));\n }\n let trust = reconDisocclusion(\n expected,\n held,\n length(vec2<f32>(mu, mv)),\n normalDot,\n here.slope + swung,\n );\n out.weight = out.colour.w * trust;\n return out;\n}\n\n/* temporalAa.ts's repeats: whether two periods' means are the same, one to zero. */\nfn reconRepeats(mean: f32, previous: f32) -> f32 {\n let apart = abs(mean - previous) / max(max(mean, previous), 1.0 / 255.0);\n return 1.0 - reconSmoothstep(RECON_FLICKER_REPEAT, 2.0 * RECON_FLICKER_REPEAT, apart);\n}\n\nstruct ReconResolved {\n /* The history's next colour, before sharpening, and the weight it has gathered. */\n colour: vec4<f32>,\n /* The pixel's next flicker record: spread, this period's sum, last period's mean, repeats. */\n record: vec4<f32>,\n /* And its next held depth swing. */\n swing: f32,\n}\n\n/* One output pixel: the history's next colour and weight, and its next flicker record. */\nfn reconResolvePixel(ox: i32, oy: i32) -> ReconResolved {\n let rw = i32(recon.renderSize.x);\n let rh = i32(recon.renderSize.y);\n let ow = i32(recon.outputSize.x);\n let oh = i32(recon.outputSize.y);\n let u = (f32(ox) + 0.5) / f32(ow);\n let v = (f32(oy) + 0.5) / f32(oh);\n let jx = recon.jitter.x;\n let jy = recon.jitter.y;\n\n /* Where this frame observed the pixel, and the render read there for the gaps. */\n let rx = u * f32(rw) + jx - 0.5;\n let ry = v * f32(rh) + jy - 0.5;\n let sample = reconSceneBicubic5(rx, ry);\n let nx = reconClampTexel(i32(reconRound(rx)), rw);\n let ny = reconClampTexel(i32(reconRound(ry)), rh);\n\n /* Each texel around: its weight, its colour in the box, and its depth. */\n var nearest = reconDepth(nx, ny);\n var dx = nx;\n var dy = ny;\n var gathered = 0.0;\n var accum = vec3<f32>(0.0);\n var neighbours: array<vec3<f32>, 9>;\n for (var j = -1; j <= 1; j = j + 1) {\n for (var i = -1; i <= 1; i = i + 1) {\n let tx = reconClampTexel(nx + i, rw);\n let ty = reconClampTexel(ny + j, rh);\n let colour = reconScene(tx, ty);\n let weight = reconWeightAt(\n ((f32(tx) + 0.5 - jx) / f32(rw)) * f32(ow) - (f32(ox) + 0.5),\n ((f32(ty) + 0.5 - jy) / f32(rh)) * f32(oh) - (f32(oy) + 0.5),\n );\n gathered = gathered + weight;\n accum = accum + colour * weight;\n neighbours[(j + 1) * 3 + (i + 1)] = reconToYCoCg(colour);\n let z = reconDepth(tx, ty);\n if (z < nearest) {\n nearest = z;\n dx = tx;\n dy = ty;\n }\n }\n }\n let box = reconVarianceBox(neighbours, recon.clampGamma);\n accum = accum / gathered;\n\n /* The history, and the weight it still deserves; a tenth of each frame is always new. */\n var swing = 0.0;\n if (recon.antiFlicker != 0u) { swing = reconSwing(ox, oy); }\n let history = reconHistoryWeight(u, v, dx, dy, swing);\n var cap = (1.0 - recon.alpha) / recon.alpha;\n var low = box.low;\n var high = box.high;\n var out: ReconResolved;\n out.record = vec4<f32>(0.0);\n out.swing = 0.0;\n /* The anti-flicker, operation for operation resolve.ts's: see temporalAa.ts. */\n if (recon.antiFlicker != 0u) {\n let seen = dot(accum, vec3<f32>(0.2126, 0.7152, 0.0722));\n let memory = recon.flickerMemory;\n let width = recon.flickerWidth;\n var held = vec4<f32>(0.0, seen * memory, seen, 0.0);\n if (history.weight > 0.0) { held = reconFlicker(ox, oy); }\n var still = 0.0;\n if (history.weight > 0.0) {\n still = 1.0 - reconSmoothstep(RECON_STILL_FROM, RECON_STILL_TO, history.moved);\n }\n let apart = abs(seen - held.z);\n let within = apart <= width * held.x + 1.0 / 255.0;\n let proven = held.w > 0.75 && within;\n var widen = 0.0;\n let base = 1.0 - recon.alpha;\n var keep = base;\n if (proven) {\n widen = width * held.x * still;\n keep = base + (RECON_FLICKER_BLEND - base) * still;\n }\n low = low - vec3<f32>(widen);\n high = high + vec3<f32>(widen);\n cap = keep / (1.0 - keep);\n var sum = held.y;\n var mean = held.z;\n var repeated = 0.0;\n if (within) { repeated = held.w; }\n if (recon.periodStart != 0u) {\n if (reconRepeats(sum, mean) > 0.5) { repeated = min(1.0, repeated + 0.5); } else { repeated = 0.0; }\n mean = sum;\n sum = 0.0;\n }\n out.record = vec4<f32>(\n held.x + (apart - held.x) * memory,\n sum + seen * memory,\n mean,\n repeated * still,\n );\n /* The peak carried on, halving over a period, whatever the test said. */\n if (history.missed >= 0.0) { out.swing = max(history.missed, swing * pow(0.5, memory)); }\n }\n let kept = min(cap, history.weight);\n\n let total = kept + gathered;\n var mixed = accum;\n if (kept > 0.0) {\n let clipped = reconClipToBox(reconToYCoCg(history.colour.xyz), low, high);\n mixed = reconAccumulate(accum, reconFromYCoCg(clipped), 1.0, gathered / total);\n }\n let known = min(1.0, total / RECON_CONFIDENT_WEIGHT);\n out.colour = vec4<f32>(sample * (1.0 - known) + mixed * known, total);\n return out;\n}\n\n/*\n * The centre pushed away from its four neighbours' mean, and held inside the range of the five \u2014\n * the halo a plain unsharp mask draws beside every edge is a value outside that range.\n */\nfn reconSharpenAt(ox: i32, oy: i32) -> vec3<f32> {\n let ow = i32(recon.outputSize.x);\n let oh = i32(recon.outputSize.y);\n let centre = reconHistory(reconClampTexel(ox, ow), reconClampTexel(oy, oh)).xyz;\n var offsets = array<vec2<i32>, 4>(\n vec2<i32>(-1, 0),\n vec2<i32>(1, 0),\n vec2<i32>(0, -1),\n vec2<i32>(0, 1),\n );\n var low = centre;\n var high = centre;\n var sum = vec3<f32>(0.0);\n for (var n = 0; n < 4; n = n + 1) {\n let at = offsets[n];\n let value = reconHistory(\n reconClampTexel(ox + at.x, ow),\n reconClampTexel(oy + at.y, oh),\n ).xyz;\n sum = sum + value;\n low = min(low, value);\n high = max(high, value);\n }\n let pushed = centre + recon.sharpenAmount * (centre - sum / 4.0);\n return min(high, max(low, pushed));\n}\n";
|
|
31
31
|
/**
|
|
32
32
|
* The parity module: the core over plain float textures written in the reference's own row order,
|
|
33
33
|
* doing its own bilinear so the comparison is arithmetic rather than a tolerance on the device's
|
|
34
34
|
* sampler.
|
|
35
35
|
*
|
|
36
|
-
* Two entry points over one set of bindings. `resolveMain` writes
|
|
37
|
-
* history — and `sharpenMain` reads that history back at binding 4
|
|
36
|
+
* Two entry points over one set of bindings. `resolveMain` writes nine floats a pixel — the next
|
|
37
|
+
* history, the next flicker record and the next depth swing — and `sharpenMain` reads that history back at binding 4
|
|
38
|
+
* and writes three.
|
|
38
39
|
*/
|
|
39
40
|
export declare function reconResolveParityWgsl(): string;
|
|
40
41
|
/**
|