@driftengine/core 3.63.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +122 -0
- package/NOTICE +20 -0
- package/README.md +1 -1
- package/dist/core/loop.js +18 -2
- package/dist/core/storage.js +5 -0
- package/dist/geometry/meshBuilder.d.ts +1 -1
- package/dist/geometry/meshBuilder.js +6 -2
- package/dist/index.d.ts +69 -4
- package/dist/index.js +112 -2
- package/dist/input/input.js +6 -1
- package/dist/math/exact.d.ts +13 -3
- package/dist/math/exact.js +68 -3
- package/dist/math/frustum.d.ts +17 -2
- package/dist/math/frustum.js +24 -0
- package/dist/render/backend/api.d.ts +34 -1
- package/dist/render/backend/api.js +22 -1
- package/dist/render/backend/budget.d.ts +7 -6
- package/dist/render/backend/budget.js +7 -6
- package/dist/render/backend/createRenderer.d.ts +57 -0
- package/dist/render/backend/createRenderer.js +51 -2
- package/dist/render/backend/materialChanges.d.ts +41 -0
- package/dist/render/backend/materialChanges.js +38 -0
- package/dist/render/backend/select.js +8 -0
- package/dist/render/backend/webgl2/renderer.d.ts +80 -1
- package/dist/render/backend/webgl2/renderer.js +208 -10
- package/dist/render/backend/webgpu/buffers.d.ts +20 -1
- package/dist/render/backend/webgpu/buffers.js +116 -58
- package/dist/render/backend/webgpu/fieldCompose.d.ts +156 -0
- package/dist/render/backend/webgpu/fieldCompose.js +396 -0
- package/dist/render/backend/webgpu/giFieldPass.d.ts +66 -0
- package/dist/render/backend/webgpu/giFieldPass.js +137 -0
- package/dist/render/backend/webgpu/gpuDrivenPass.d.ts +728 -0
- package/dist/render/backend/webgpu/gpuDrivenPass.js +2473 -0
- package/dist/render/backend/webgpu/linePass.d.ts +4 -14
- package/dist/render/backend/webgpu/linePass.js +4 -33
- package/dist/render/backend/webgpu/probeBake.d.ts +148 -0
- package/dist/render/backend/webgpu/probeBake.js +493 -0
- package/dist/render/backend/webgpu/renderer.d.ts +379 -24
- package/dist/render/backend/webgpu/renderer.js +1369 -76
- package/dist/render/backend/webgpu/scatterPass.js +15 -1
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +19 -9
- package/dist/render/backend/webgpu/surfaceTexturePass.js +58 -32
- package/dist/render/causticsRenderer.d.ts +3 -1
- package/dist/render/causticsRenderer.js +4 -1
- package/dist/render/depthConvention.d.ts +12 -0
- package/dist/render/depthConvention.js +14 -0
- package/dist/render/deviceFeatures.d.ts +32 -0
- package/dist/render/deviceFeatures.js +41 -0
- package/dist/render/fog.d.ts +79 -0
- package/dist/render/fog.js +138 -0
- package/dist/render/frame/alias.d.ts +30 -0
- package/dist/render/frame/alias.js +61 -0
- package/dist/render/frame/deps.d.ts +37 -0
- package/dist/render/frame/deps.js +122 -0
- package/dist/render/frame/flushGraph.d.ts +43 -0
- package/dist/render/frame/flushGraph.js +84 -0
- package/dist/render/frame/graphSchedule.d.ts +49 -0
- package/dist/render/frame/graphSchedule.js +120 -0
- package/dist/render/frame/index.d.ts +15 -0
- package/dist/render/frame/index.js +8 -0
- package/dist/render/frame/lifetime.d.ts +24 -0
- package/dist/render/frame/lifetime.js +36 -0
- package/dist/render/frame/passTimings.d.ts +42 -0
- package/dist/render/frame/passTimings.js +38 -0
- package/dist/render/frame/validate.d.ts +15 -0
- package/dist/render/frame/validate.js +22 -0
- package/dist/render/frame/virtual.d.ts +44 -0
- package/dist/render/frame/virtual.js +61 -0
- package/dist/render/gi/chain.d.ts +82 -0
- package/dist/render/gi/chain.js +135 -0
- package/dist/render/gi/denoise.d.ts +114 -0
- package/dist/render/gi/denoise.js +169 -0
- package/dist/render/gi/fieldScene.d.ts +125 -0
- package/dist/render/gi/fieldScene.js +219 -0
- package/dist/render/gi/globalField.d.ts +157 -0
- package/dist/render/gi/globalField.js +373 -0
- package/dist/render/gi/probeGridFit.d.ts +24 -0
- package/dist/render/gi/probeGridFit.js +71 -0
- package/dist/render/gi/probeTrace.d.ts +82 -0
- package/dist/render/gi/probeTrace.js +128 -0
- package/dist/render/gi/probeVolume.d.ts +136 -0
- package/dist/render/gi/probeVolume.js +191 -0
- package/dist/render/gi/reflection.d.ts +73 -0
- package/dist/render/gi/reflection.js +109 -0
- package/dist/render/gi/traceField.d.ts +91 -0
- package/dist/render/gi/traceField.js +129 -0
- package/dist/render/gi/traceScreen.d.ts +68 -0
- package/dist/render/gi/traceScreen.js +82 -0
- package/dist/render/gpuScene.d.ts +38 -0
- package/dist/render/gpuScene.js +41 -0
- package/dist/render/gpudriven/alphaTest.d.ts +28 -0
- package/dist/render/gpudriven/alphaTest.js +32 -0
- package/dist/render/gpudriven/clusterUpload.d.ts +59 -0
- package/dist/render/gpudriven/clusterUpload.js +75 -0
- package/dist/render/gpudriven/clusterWorld.d.ts +57 -0
- package/dist/render/gpudriven/clusterWorld.js +155 -0
- package/dist/render/gpudriven/compact.d.ts +51 -0
- package/dist/render/gpudriven/compact.js +68 -0
- package/dist/render/gpudriven/cullClusters.d.ts +129 -0
- package/dist/render/gpudriven/cullClusters.js +237 -0
- package/dist/render/gpudriven/decodeTables.d.ts +64 -0
- package/dist/render/gpudriven/decodeTables.js +219 -0
- package/dist/render/gpudriven/frustum.d.ts +25 -0
- package/dist/render/gpudriven/frustum.js +59 -0
- package/dist/render/gpudriven/geometryHarness.d.ts +15 -0
- package/dist/render/gpudriven/geometryHarness.js +31 -0
- package/dist/render/gpudriven/hzb.d.ts +60 -0
- package/dist/render/gpudriven/hzb.js +97 -0
- package/dist/render/gpudriven/ibl.d.ts +85 -0
- package/dist/render/gpudriven/ibl.js +129 -0
- package/dist/render/gpudriven/indirect.d.ts +67 -0
- package/dist/render/gpudriven/indirect.js +77 -0
- package/dist/render/gpudriven/instances.d.ts +43 -0
- package/dist/render/gpudriven/instances.js +172 -0
- package/dist/render/gpudriven/lit.d.ts +165 -0
- package/dist/render/gpudriven/lit.js +165 -0
- package/dist/render/gpudriven/lodCut.d.ts +28 -0
- package/dist/render/gpudriven/lodCut.js +38 -0
- package/dist/render/gpudriven/materialBin.d.ts +60 -0
- package/dist/render/gpudriven/materialBin.js +108 -0
- package/dist/render/gpudriven/materialTable.d.ts +88 -0
- package/dist/render/gpudriven/materialTable.js +115 -0
- package/dist/render/gpudriven/pipeline.d.ts +135 -0
- package/dist/render/gpudriven/pipeline.js +237 -0
- package/dist/render/gpudriven/rangeAlloc.d.ts +50 -0
- package/dist/render/gpudriven/rangeAlloc.js +112 -0
- package/dist/render/gpudriven/sceneUpload.d.ts +96 -0
- package/dist/render/gpudriven/sceneUpload.js +115 -0
- package/dist/render/gpudriven/shadeBins.d.ts +92 -0
- package/dist/render/gpudriven/shadeBins.js +182 -0
- package/dist/render/gpudriven/shadow.d.ts +136 -0
- package/dist/render/gpudriven/shadow.js +224 -0
- package/dist/render/gpudriven/shadowCamera.d.ts +87 -0
- package/dist/render/gpudriven/shadowCamera.js +345 -0
- package/dist/render/gpudriven/streamScene.d.ts +194 -0
- package/dist/render/gpudriven/streamScene.js +459 -0
- package/dist/render/gpudriven/surfaceFrame.d.ts +25 -0
- package/dist/render/gpudriven/surfaceFrame.js +51 -0
- package/dist/render/gpudriven/twoPhase.d.ts +122 -0
- package/dist/render/gpudriven/twoPhase.js +160 -0
- package/dist/render/gpudriven/visbuffer.d.ts +25 -0
- package/dist/render/gpudriven/visbuffer.js +37 -0
- package/dist/render/halfFloat.d.ts +10 -0
- package/dist/render/halfFloat.js +23 -4
- package/dist/render/inference/attentionTiled.d.ts +27 -0
- package/dist/render/inference/attentionTiled.js +117 -0
- package/dist/render/inference/denseKernels.d.ts +29 -0
- package/dist/render/inference/denseKernels.js +312 -0
- package/dist/render/inference/device.d.ts +21 -0
- package/dist/render/inference/device.js +32 -0
- package/dist/render/inference/deviceGraph.d.ts +34 -0
- package/dist/render/inference/deviceGraph.js +17 -0
- package/dist/render/inference/fuse.d.ts +15 -0
- package/dist/render/inference/fuse.js +37 -0
- package/dist/render/inference/kernelKit.d.ts +52 -0
- package/dist/render/inference/kernelKit.js +70 -0
- package/dist/render/inference/kernels.d.ts +3 -0
- package/dist/render/inference/kernels.js +11 -0
- package/dist/render/inference/plan.d.ts +13 -0
- package/dist/render/inference/plan.js +18 -0
- package/dist/render/inference/reuse.d.ts +39 -0
- package/dist/render/inference/reuse.js +65 -0
- package/dist/render/inference/runner.d.ts +31 -0
- package/dist/render/inference/runner.js +175 -0
- package/dist/render/inference/schedule.d.ts +39 -0
- package/dist/render/inference/schedule.js +59 -0
- package/dist/render/inference/shapeKernels.d.ts +10 -0
- package/dist/render/inference/shapeKernels.js +80 -0
- package/dist/render/inference/spatialKernels.d.ts +21 -0
- package/dist/render/inference/spatialKernels.js +179 -0
- package/dist/render/inference/splatRaster.wgsl.d.ts +75 -0
- package/dist/render/inference/splatRaster.wgsl.js +337 -0
- package/dist/render/inference/splatTiles.d.ts +79 -0
- package/dist/render/inference/splatTiles.js +161 -0
- package/dist/render/lineBatch.d.ts +2 -5
- package/dist/render/lineBatch.js +4 -24
- package/dist/render/mesh.d.ts +4 -0
- package/dist/render/mesh.js +45 -1
- package/dist/render/pass.d.ts +145 -8
- package/dist/render/prefilterEnvMap.d.ts +22 -0
- package/dist/render/prefilterEnvMap.js +31 -0
- package/dist/render/readback.d.ts +30 -0
- package/dist/render/readback.js +47 -0
- package/dist/render/recon/clamp.d.ts +36 -0
- package/dist/render/recon/clamp.js +92 -0
- package/dist/render/recon/disocclusion.d.ts +60 -0
- package/dist/render/recon/disocclusion.js +109 -0
- package/dist/render/recon/frameGen.d.ts +81 -0
- package/dist/render/recon/frameGen.js +150 -0
- package/dist/render/recon/frameSizes.d.ts +34 -0
- package/dist/render/recon/frameSizes.js +58 -0
- package/dist/render/recon/jitter.d.ts +60 -0
- package/dist/render/recon/jitter.js +118 -0
- package/dist/render/recon/motionVectors.d.ts +55 -0
- package/dist/render/recon/motionVectors.js +107 -0
- package/dist/render/recon/reproject.d.ts +41 -0
- package/dist/render/recon/reproject.js +131 -0
- package/dist/render/recon/resolve.d.ts +90 -0
- package/dist/render/recon/resolve.js +313 -0
- package/dist/render/recon/tier.d.ts +24 -0
- package/dist/render/recon/tier.js +8 -0
- package/dist/render/reflectionProbe.d.ts +26 -0
- package/dist/render/reflectionProbe.js +33 -0
- package/dist/render/renderQuality.d.ts +69 -0
- package/dist/render/renderQuality.js +22 -0
- package/dist/render/screenSpaceReflection.d.ts +23 -0
- package/dist/render/screenSpaceReflection.js +22 -3
- package/dist/render/sdfFont.js +2 -0
- package/dist/render/segmentQuads.d.ts +13 -0
- package/dist/render/segmentQuads.js +32 -0
- package/dist/render/shaders/flat/lobes.d.ts +27 -0
- package/dist/render/shaders/flat/lobes.js +33 -3
- package/dist/render/shaders/flat/preamble.d.ts +7 -0
- package/dist/render/shaders/flat/preamble.js +24 -1
- package/dist/render/shaders/flat/probeGrid.d.ts +1 -1
- package/dist/render/shaders/flat/probeGrid.js +71 -2
- package/dist/render/shaders/generated/flat.wgsl.d.ts +48 -8
- package/dist/render/shaders/generated/flat.wgsl.js +64 -24
- package/dist/render/shaders/gi/composeField.wgsl.d.ts +56 -0
- package/dist/render/shaders/gi/composeField.wgsl.js +231 -0
- package/dist/render/shaders/gi/marchField.wgsl.d.ts +30 -0
- package/dist/render/shaders/gi/marchField.wgsl.js +141 -0
- package/dist/render/shaders/gi/probeBake.wgsl.d.ts +113 -0
- package/dist/render/shaders/gi/probeBake.wgsl.js +635 -0
- package/dist/render/shaders/gi/probeTrace.wgsl.d.ts +72 -0
- package/dist/render/shaders/gi/probeTrace.wgsl.js +261 -0
- package/dist/render/shaders/gi/probeVolume.wgsl.d.ts +49 -0
- package/dist/render/shaders/gi/probeVolume.wgsl.js +242 -0
- package/dist/render/shaders/gi/sampleField.wgsl.d.ts +32 -0
- package/dist/render/shaders/gi/sampleField.wgsl.js +134 -0
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.d.ts +26 -0
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.js +339 -0
- package/dist/render/shaders/gpudriven/compact.wgsl.d.ts +29 -0
- package/dist/render/shaders/gpudriven/compact.wgsl.js +58 -0
- package/dist/render/shaders/gpudriven/cull.wgsl.d.ts +90 -0
- package/dist/render/shaders/gpudriven/cull.wgsl.js +423 -0
- package/dist/render/shaders/gpudriven/decode.wgsl.d.ts +72 -0
- package/dist/render/shaders/gpudriven/decode.wgsl.js +349 -0
- package/dist/render/shaders/gpudriven/environment.wgsl.d.ts +44 -0
- package/dist/render/shaders/gpudriven/environment.wgsl.js +137 -0
- package/dist/render/shaders/gpudriven/fog.wgsl.d.ts +28 -0
- package/dist/render/shaders/gpudriven/fog.wgsl.js +107 -0
- package/dist/render/shaders/gpudriven/frameBlock.wgsl.d.ts +13 -0
- package/dist/render/shaders/gpudriven/frameBlock.wgsl.js +62 -0
- package/dist/render/shaders/gpudriven/materialBin.wgsl.d.ts +51 -0
- package/dist/render/shaders/gpudriven/materialBin.wgsl.js +112 -0
- package/dist/render/shaders/gpudriven/materialTable.wgsl.d.ts +25 -0
- package/dist/render/shaders/gpudriven/materialTable.wgsl.js +43 -0
- package/dist/render/shaders/gpudriven/meshTransform.wgsl.d.ts +18 -0
- package/dist/render/shaders/gpudriven/meshTransform.wgsl.js +37 -0
- package/dist/render/shaders/gpudriven/present.wgsl.d.ts +43 -0
- package/dist/render/shaders/gpudriven/present.wgsl.js +127 -0
- package/dist/render/shaders/gpudriven/shade.wgsl.d.ts +127 -0
- package/dist/render/shaders/gpudriven/shade.wgsl.js +874 -0
- package/dist/render/shaders/gpudriven/shadow.wgsl.d.ts +44 -0
- package/dist/render/shaders/gpudriven/shadow.wgsl.js +308 -0
- package/dist/render/shaders/gpudriven/visbufferRaster.wgsl.d.ts +28 -0
- package/dist/render/shaders/gpudriven/visbufferRaster.wgsl.js +245 -0
- package/dist/render/shaders/network.wgsl.d.ts +101 -0
- package/dist/render/shaders/network.wgsl.js +206 -0
- package/dist/render/shaders/recon/motion.wgsl.d.ts +44 -0
- package/dist/render/shaders/recon/motion.wgsl.js +96 -0
- package/dist/render/shaders/recon/resolve.wgsl.d.ts +51 -0
- package/dist/render/shaders/recon/resolve.wgsl.js +733 -0
- package/dist/render/temporalAa.js +8 -33
- package/dist/render/textLayout.js +12 -6
- package/dist/render/textRenderer.d.ts +3 -1
- package/dist/render/textRenderer.js +4 -1
- package/dist/render/translucentQueue.d.ts +6 -0
- package/dist/render/translucentQueue.js +11 -0
- package/dist/render/windStreakRenderer.d.ts +2 -1
- package/dist/render/windStreakRenderer.js +3 -1
- package/dist/world/cell.d.ts +63 -0
- package/dist/world/cell.js +181 -0
- package/dist/world/cellStream.d.ts +103 -0
- package/dist/world/cellStream.js +198 -0
- package/dist/world/freeze.d.ts +81 -0
- package/dist/world/freeze.js +114 -0
- package/dist/world/rebase.d.ts +29 -0
- package/dist/world/rebase.js +41 -0
- package/package.json +8 -3
- package/scripts/frames.mjs +92 -0
- package/scripts/gpuCompute.mjs +323 -0
- package/scripts/png.d.mts +16 -0
- package/scripts/png.mjs +25 -0
- package/src/core/loop.ts +19 -2
- package/src/core/storage.ts +5 -0
- package/src/geometry/meshBuilder.ts +5 -1
- package/src/index.ts +246 -4
- package/src/input/input.ts +6 -1
- package/src/math/exact.ts +69 -3
- package/src/math/frustum.ts +52 -3
- package/src/render/backend/api.ts +42 -1
- package/src/render/backend/budget.ts +7 -6
- package/src/render/backend/createRenderer.ts +92 -3
- package/src/render/backend/materialChanges.ts +54 -0
- package/src/render/backend/select.ts +8 -0
- package/src/render/backend/webgl2/renderer.ts +211 -9
- package/src/render/backend/webgpu/buffers.ts +182 -69
- package/src/render/backend/webgpu/fieldCompose.ts +482 -0
- package/src/render/backend/webgpu/giFieldPass.ts +200 -0
- package/src/render/backend/webgpu/gpuDrivenPass.ts +2993 -0
- package/src/render/backend/webgpu/linePass.ts +4 -39
- package/src/render/backend/webgpu/probeBake.ts +588 -0
- package/src/render/backend/webgpu/renderer.ts +1481 -76
- package/src/render/backend/webgpu/scatterPass.ts +15 -1
- package/src/render/backend/webgpu/surfaceTexturePass.ts +63 -36
- package/src/render/causticsRenderer.ts +5 -2
- package/src/render/depthConvention.ts +15 -0
- package/src/render/deviceFeatures.ts +77 -0
- package/src/render/fog.ts +185 -0
- package/src/render/frame/alias.ts +97 -0
- package/src/render/frame/deps.ts +155 -0
- package/src/render/frame/flushGraph.ts +135 -0
- package/src/render/frame/graphSchedule.ts +170 -0
- package/src/render/frame/index.ts +52 -0
- package/src/render/frame/lifetime.ts +61 -0
- package/src/render/frame/passTimings.ts +69 -0
- package/src/render/frame/validate.ts +40 -0
- package/src/render/frame/virtual.ts +91 -0
- package/src/render/gi/chain.ts +225 -0
- package/src/render/gi/denoise.ts +276 -0
- package/src/render/gi/fieldScene.ts +264 -0
- package/src/render/gi/globalField.ts +543 -0
- package/src/render/gi/probeGridFit.ts +89 -0
- package/src/render/gi/probeTrace.ts +143 -0
- package/src/render/gi/probeVolume.ts +288 -0
- package/src/render/gi/reflection.ts +163 -0
- package/src/render/gi/traceField.ts +223 -0
- package/src/render/gi/traceScreen.ts +106 -0
- package/src/render/gpuScene.ts +80 -0
- package/src/render/gpudriven/alphaTest.ts +33 -0
- package/src/render/gpudriven/clusterUpload.ts +123 -0
- package/src/render/gpudriven/clusterWorld.ts +239 -0
- package/src/render/gpudriven/compact.ts +80 -0
- package/src/render/gpudriven/cullClusters.ts +333 -0
- package/src/render/gpudriven/decodeTables.ts +332 -0
- package/src/render/gpudriven/frustum.ts +70 -0
- package/src/render/gpudriven/geometryHarness.ts +51 -0
- package/src/render/gpudriven/hzb.ts +113 -0
- package/src/render/gpudriven/ibl.ts +147 -0
- package/src/render/gpudriven/indirect.ts +89 -0
- package/src/render/gpudriven/instances.ts +234 -0
- package/src/render/gpudriven/lit.ts +329 -0
- package/src/render/gpudriven/lodCut.ts +62 -0
- package/src/render/gpudriven/materialBin.ts +131 -0
- package/src/render/gpudriven/materialTable.ts +164 -0
- package/src/render/gpudriven/pipeline.ts +336 -0
- package/src/render/gpudriven/rangeAlloc.ts +122 -0
- package/src/render/gpudriven/sceneUpload.ts +173 -0
- package/src/render/gpudriven/shadeBins.ts +222 -0
- package/src/render/gpudriven/shadow.ts +285 -0
- package/src/render/gpudriven/shadowCamera.ts +406 -0
- package/src/render/gpudriven/streamScene.ts +575 -0
- package/src/render/gpudriven/surfaceFrame.ts +68 -0
- package/src/render/gpudriven/twoPhase.ts +214 -0
- package/src/render/gpudriven/visbuffer.ts +41 -0
- package/src/render/halfFloat.ts +22 -4
- package/src/render/inference/attentionTiled.ts +132 -0
- package/src/render/inference/denseKernels.ts +369 -0
- package/src/render/inference/device.ts +44 -0
- package/src/render/inference/deviceGraph.ts +39 -0
- package/src/render/inference/fuse.ts +47 -0
- package/src/render/inference/kernelKit.ts +120 -0
- package/src/render/inference/kernels.ts +18 -0
- package/src/render/inference/plan.ts +26 -0
- package/src/render/inference/reuse.ts +79 -0
- package/src/render/inference/runner.ts +204 -0
- package/src/render/inference/schedule.ts +80 -0
- package/src/render/inference/shapeKernels.ts +112 -0
- package/src/render/inference/spatialKernels.ts +220 -0
- package/src/render/inference/splatRaster.wgsl.ts +348 -0
- package/src/render/inference/splatTiles.ts +186 -0
- package/src/render/lineBatch.ts +4 -24
- package/src/render/mesh.ts +46 -1
- package/src/render/pass.ts +155 -10
- package/src/render/prefilterEnvMap.ts +33 -0
- package/src/render/readback.ts +73 -0
- package/src/render/recon/clamp.ts +113 -0
- package/src/render/recon/disocclusion.ts +143 -0
- package/src/render/recon/frameGen.ts +191 -0
- package/src/render/recon/frameSizes.ts +64 -0
- package/src/render/recon/jitter.ts +126 -0
- package/src/render/recon/motionVectors.ts +138 -0
- package/src/render/recon/reproject.ts +179 -0
- package/src/render/recon/resolve.ts +444 -0
- package/src/render/recon/tier.ts +31 -0
- package/src/render/reflectionProbe.ts +34 -0
- package/src/render/renderQuality.ts +87 -0
- package/src/render/screenSpaceReflection.ts +37 -3
- package/src/render/sdfFont.ts +2 -0
- package/src/render/segmentQuads.ts +39 -0
- package/src/render/shaders/flat/lobes.ts +35 -3
- package/src/render/shaders/flat/preamble.ts +25 -1
- package/src/render/shaders/flat/probeGrid.ts +77 -2
- package/src/render/shaders/generated/flat.wgsl.ts +64 -24
- package/src/render/shaders/gi/composeField.wgsl.ts +239 -0
- package/src/render/shaders/gi/marchField.wgsl.ts +146 -0
- package/src/render/shaders/gi/probeBake.wgsl.ts +649 -0
- package/src/render/shaders/gi/probeTrace.wgsl.ts +269 -0
- package/src/render/shaders/gi/probeVolume.wgsl.ts +246 -0
- package/src/render/shaders/gi/sampleField.wgsl.ts +140 -0
- package/src/render/shaders/gpudriven/blendRaster.wgsl.ts +343 -0
- package/src/render/shaders/gpudriven/compact.wgsl.ts +59 -0
- package/src/render/shaders/gpudriven/cull.wgsl.ts +433 -0
- package/src/render/shaders/gpudriven/decode.wgsl.ts +373 -0
- package/src/render/shaders/gpudriven/environment.wgsl.ts +141 -0
- package/src/render/shaders/gpudriven/fog.wgsl.ts +110 -0
- package/src/render/shaders/gpudriven/frameBlock.wgsl.ts +62 -0
- package/src/render/shaders/gpudriven/materialBin.wgsl.ts +116 -0
- package/src/render/shaders/gpudriven/materialTable.wgsl.ts +46 -0
- package/src/render/shaders/gpudriven/meshTransform.wgsl.ts +37 -0
- package/src/render/shaders/gpudriven/present.wgsl.ts +129 -0
- package/src/render/shaders/gpudriven/shade.wgsl.ts +884 -0
- package/src/render/shaders/gpudriven/shadow.wgsl.ts +322 -0
- package/src/render/shaders/gpudriven/visbufferRaster.wgsl.ts +251 -0
- package/src/render/shaders/network.wgsl.ts +238 -0
- package/src/render/shaders/recon/motion.wgsl.ts +101 -0
- package/src/render/shaders/recon/resolve.wgsl.ts +741 -0
- package/src/render/temporalAa.ts +9 -33
- package/src/render/textLayout.ts +12 -6
- package/src/render/textRenderer.ts +5 -2
- package/src/render/translucentQueue.ts +11 -0
- package/src/render/windStreakRenderer.ts +4 -2
- package/src/world/cell.ts +231 -0
- package/src/world/cellStream.ts +278 -0
- package/src/world/freeze.ts +157 -0
- package/src/world/rebase.ts +56 -0
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
import { MATERIAL_SLOTS, MATERIAL_TABLE_WGSL } from './materialTable.wgsl.ts';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The device half of the GPU-driven pipeline's arithmetic.
|
|
5
|
+
*
|
|
6
|
+
* **Hand-written WGSL, which is the exception this directory exists to record.** Every other
|
|
7
|
+
* shader in this engine is authored in GLSL and generated to WGSL by `scripts/wgsl.ts`, and that
|
|
8
|
+
* direction is the safety property of the WebGPU backend: a defect in the generator can only reach
|
|
9
|
+
* WebGPU, never the path that runs everywhere. These have no GLSL original because WebGL2 has no
|
|
10
|
+
* compute stage at all — `indirectSupport(backend)` is false there, which §3 row 2 already records
|
|
11
|
+
* — so there is nothing to generate them from and nothing they could break by being wrong.
|
|
12
|
+
*
|
|
13
|
+
* **What keeps them honest is `scripts/gpu-parity.mjs`.** The same arithmetic lives in
|
|
14
|
+
* `render/gpudriven/*.ts` as the reference, and that script runs both over generated input on a
|
|
15
|
+
* real device and requires them to agree. One authored expression, two consumers, one test that
|
|
16
|
+
* they have not drifted — the discipline `splats` established for shaders that *can* be generated,
|
|
17
|
+
* applied where they cannot.
|
|
18
|
+
*
|
|
19
|
+
* Every entry point takes its inputs as storage buffers and writes one result per invocation, so a
|
|
20
|
+
* harness can bind them without knowing what any of them mean.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Plane extraction and the sphere test, one flag a mesh. Mirrors `gpudriven/frustum.ts`, and
|
|
25
|
+
* `gpudriven/instances.ts` says what the frame does with the flag: the cut reads it.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Floats in the cluster cull's settings: the eye, the pyramid switch, its shape, the count, and
|
|
29
|
+
* the cone switch. One number the pass allocates, writes and the shader declares.
|
|
30
|
+
*/
|
|
31
|
+
export const CULL_SETTINGS_FLOATS = 9;
|
|
32
|
+
/** Where in those settings the cone switch sits. One for the visibility raster, zero for blending. */
|
|
33
|
+
export const CULL_CONES = 8;
|
|
34
|
+
|
|
35
|
+
export const CULL_INSTANCES_WGSL = `
|
|
36
|
+
@group(0) @binding(0) var<storage, read> viewProj: array<f32, 16>;
|
|
37
|
+
@group(0) @binding(1) var<storage, read> spheres: array<f32>;
|
|
38
|
+
@group(0) @binding(2) var<storage, read_write> culled: array<u32>;
|
|
39
|
+
|
|
40
|
+
fn setPlane(a: f32, b: f32, c: f32, d: f32) -> vec4<f32> {
|
|
41
|
+
let length = sqrt(a * a + b * b + c * c);
|
|
42
|
+
let k = select(0.0, 1.0 / length, length > 0.0);
|
|
43
|
+
return vec4<f32>(a * k, b * k, c * k, d * k);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fn planeAt(index: u32) -> vec4<f32> {
|
|
47
|
+
let m = &viewProj;
|
|
48
|
+
let r0 = vec4<f32>((*m)[0], (*m)[4], (*m)[8], (*m)[12]);
|
|
49
|
+
let r1 = vec4<f32>((*m)[1], (*m)[5], (*m)[9], (*m)[13]);
|
|
50
|
+
let r2 = vec4<f32>((*m)[2], (*m)[6], (*m)[10], (*m)[14]);
|
|
51
|
+
let r3 = vec4<f32>((*m)[3], (*m)[7], (*m)[11], (*m)[15]);
|
|
52
|
+
switch index {
|
|
53
|
+
case 0u: { return setPlane(r3.x + r0.x, r3.y + r0.y, r3.z + r0.z, r3.w + r0.w); }
|
|
54
|
+
case 1u: { return setPlane(r3.x - r0.x, r3.y - r0.y, r3.z - r0.z, r3.w - r0.w); }
|
|
55
|
+
case 2u: { return setPlane(r3.x + r1.x, r3.y + r1.y, r3.z + r1.z, r3.w + r1.w); }
|
|
56
|
+
case 3u: { return setPlane(r3.x - r1.x, r3.y - r1.y, r3.z - r1.z, r3.w - r1.w); }
|
|
57
|
+
/* The two depth planes, in clip terms rather than near/far terms: reversed-Z swaps which
|
|
58
|
+
physical plane each one is, and a sphere satisfying both is inside either way. */
|
|
59
|
+
case 4u: { return setPlane(r2.x, r2.y, r2.z, r2.w); }
|
|
60
|
+
default: { return setPlane(r3.x - r2.x, r3.y - r2.y, r3.z - r2.z, r3.w - r2.w); }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@compute @workgroup_size(64)
|
|
65
|
+
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
66
|
+
let i = id.x;
|
|
67
|
+
if (i * 4u + 3u >= arrayLength(&spheres)) { return; }
|
|
68
|
+
let centre = vec3<f32>(spheres[i * 4u], spheres[i * 4u + 1u], spheres[i * 4u + 2u]);
|
|
69
|
+
let radius = spheres[i * 4u + 3u];
|
|
70
|
+
|
|
71
|
+
var outside = 0u;
|
|
72
|
+
for (var p = 0u; p < 6u; p = p + 1u) {
|
|
73
|
+
let plane = planeAt(p);
|
|
74
|
+
let distance = dot(plane.xyz, centre) + plane.w;
|
|
75
|
+
/* Conservative in one direction only: a sphere straddling a plane survives, because culling
|
|
76
|
+
something visible is a hole in the picture and keeping something invisible is a wasted draw. */
|
|
77
|
+
if (distance < -radius) { outside = 1u; }
|
|
78
|
+
}
|
|
79
|
+
culled[i] = outside;
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The level-of-detail cut, with the meshes the instance cull hid left out. Mirrors
|
|
85
|
+
* `selectClusters` in `gpudriven/instances.ts`, over `gpudriven/lodCut.ts`'s rule.
|
|
86
|
+
*
|
|
87
|
+
* **The mesh is read from the cluster's four meta words** rather than from a buffer of its own:
|
|
88
|
+
* the frame already uploads them for the raster, and a binding is a thing a stage has eight of.
|
|
89
|
+
*
|
|
90
|
+
* **It runs twice where a scene has a blended material**, once for each half of the frame, and
|
|
91
|
+
* `params[6]` is which half is being asked for. A visibility buffer holds one surface a pixel, so
|
|
92
|
+
* a blended cluster cannot go through it at all; what the two runs share is this question — which
|
|
93
|
+
* clusters, at which level of detail — which is the same question for a pane of glass as for a
|
|
94
|
+
* wall and is the whole reason the front half of the pipeline is reusable. A scene with nothing
|
|
95
|
+
* blended runs this once and the filter costs it one comparison against a uniform.
|
|
96
|
+
*/
|
|
97
|
+
export const LOD_CUT_WGSL = /* wgsl */ `
|
|
98
|
+
struct Params {
|
|
99
|
+
screenHeight: f32,
|
|
100
|
+
fovY: f32,
|
|
101
|
+
thresholdPixels: f32,
|
|
102
|
+
eyeX: f32,
|
|
103
|
+
eyeY: f32,
|
|
104
|
+
eyeZ: f32,
|
|
105
|
+
/** Non-zero to select the blended clusters, zero to select everything else. */
|
|
106
|
+
wantBlend: f32,
|
|
107
|
+
};
|
|
108
|
+
${MATERIAL_TABLE_WGSL}
|
|
109
|
+
@group(0) @binding(0) var<storage, read> params: array<f32, 7>;
|
|
110
|
+
/** Six floats a cluster: centre, radius, own error, parent error. */
|
|
111
|
+
@group(0) @binding(1) var<storage, read> clusters: array<f32>;
|
|
112
|
+
@group(0) @binding(2) var<storage, read_write> selected: array<u32>;
|
|
113
|
+
/** Four words a cluster: index offset, index count, identifier, mesh. */
|
|
114
|
+
@group(0) @binding(3) var<storage, read> clusterMeta: array<u32>;
|
|
115
|
+
/** One word a mesh, nonzero where CULL_INSTANCES_WGSL found it wholly outside the view. */
|
|
116
|
+
@group(0) @binding(4) var<storage, read> instanceHidden: array<u32>;
|
|
117
|
+
/** One material a cluster, and the table it indexes. Both only to read one flag. */
|
|
118
|
+
@group(0) @binding(5) var<storage, read> materialOf: array<u32>;
|
|
119
|
+
@group(0) @binding(6) var<uniform> materials: array<Material, ${MATERIAL_SLOTS}>;
|
|
120
|
+
|
|
121
|
+
fn projectedError(error: f32, distance: f32, radius: f32, screenHeight: f32, fovY: f32) -> f32 {
|
|
122
|
+
let safe = max(max(distance, radius), 1e-4);
|
|
123
|
+
let scale = screenHeight / (2.0 * tan(fovY * 0.5));
|
|
124
|
+
return (error * scale) / safe;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@compute @workgroup_size(64)
|
|
128
|
+
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
129
|
+
let i = id.x;
|
|
130
|
+
if (i * 6u + 5u >= arrayLength(&clusters)) { return; }
|
|
131
|
+
/* A hidden mesh contributes nothing, so none of its clusters is in the cut at any level. */
|
|
132
|
+
if (instanceHidden[clusterMeta[i * 4u + 3u]] != 0u) {
|
|
133
|
+
selected[i] = 0u;
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
/*
|
|
137
|
+
* **Which half of the frame this cluster belongs to, asked once.** The two halves are exclusive:
|
|
138
|
+
* a blended cluster is not in the opaque cut and an opaque one is not in the blended cut, so
|
|
139
|
+
* neither is drawn twice and neither is dropped. The flag is read through a uniform by an index
|
|
140
|
+
* that is the same for every cluster of a mesh, so the branch is as coherent as this shader gets.
|
|
141
|
+
*/
|
|
142
|
+
let blended = materials[min(materialOf[i], ${MATERIAL_SLOTS - 1}u)].orm.w != 0.0;
|
|
143
|
+
if (blended != (params[6] != 0.0)) {
|
|
144
|
+
selected[i] = 0u;
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
let screenHeight = params[0];
|
|
148
|
+
let fovY = params[1];
|
|
149
|
+
let threshold = params[2];
|
|
150
|
+
let eye = vec3<f32>(params[3], params[4], params[5]);
|
|
151
|
+
|
|
152
|
+
let centre = vec3<f32>(clusters[i * 6u], clusters[i * 6u + 1u], clusters[i * 6u + 2u]);
|
|
153
|
+
let radius = clusters[i * 6u + 3u];
|
|
154
|
+
let ownError = clusters[i * 6u + 4u];
|
|
155
|
+
let parentError = clusters[i * 6u + 5u];
|
|
156
|
+
let distance = length(centre - eye);
|
|
157
|
+
|
|
158
|
+
let own = projectedError(ownError, distance, radius, screenHeight, fovY);
|
|
159
|
+
let parent = projectedError(parentError, distance, radius, screenHeight, fovY);
|
|
160
|
+
/* Both halves: the first alone draws every ancestor too, the second alone draws nothing. */
|
|
161
|
+
selected[i] = select(0u, 1u, own <= threshold && parent > threshold);
|
|
162
|
+
}
|
|
163
|
+
`;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* The pyramid's base level, copied out of the depth attachment a phase drew into.
|
|
167
|
+
*
|
|
168
|
+
* **A copy and nothing else, which is the point.** `HZB_REDUCE_WGSL` below does every reduction,
|
|
169
|
+
* and it is checked against `hzb.ts` texel by texel; putting a first reduction here would be a
|
|
170
|
+
* second place for the fold to be wrong and the one place nothing compares. What this does have
|
|
171
|
+
* is an index, and an index that is wrong draws a pyramid of somebody else's depth — which is
|
|
172
|
+
* unmistakable rather than subtle, because the occlusion then culls the picture.
|
|
173
|
+
*
|
|
174
|
+
* **A depth attachment cannot be read as a buffer and the reduction reads a buffer**, which is
|
|
175
|
+
* the whole reason this dispatch exists. `texture_depth_2d` binds the attachment the render pass
|
|
176
|
+
* wrote, in a later pass, and `textureLoad` needs no sampler.
|
|
177
|
+
*/
|
|
178
|
+
export const HZB_SEED_WGSL = `
|
|
179
|
+
/** width, height. The base level starts at zero, which is what makes it the base level. */
|
|
180
|
+
@group(0) @binding(0) var<storage, read> size: array<u32, 2>;
|
|
181
|
+
@group(0) @binding(1) var depth: texture_depth_2d;
|
|
182
|
+
@group(0) @binding(2) var<storage, read_write> pyramid: array<f32>;
|
|
183
|
+
|
|
184
|
+
@compute @workgroup_size(8, 8)
|
|
185
|
+
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
186
|
+
let width = size[0];
|
|
187
|
+
if (id.x >= width || id.y >= size[1]) { return; }
|
|
188
|
+
pyramid[id.y * width + id.x] = textureLoad(depth, vec2<i32>(i32(id.x), i32(id.y)), 0);
|
|
189
|
+
}
|
|
190
|
+
`;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* A light's pyramid's base, from its shadow map: half the map, the furthest of each group, turned
|
|
194
|
+
* over into the camera's convention. Mirrors `shadowPyramidBase` in `gpudriven/hzb.ts`, which says
|
|
195
|
+
* why it is turned over and why it is half.
|
|
196
|
+
*
|
|
197
|
+
* **Not a copy, as the camera's seed is**, and so not unchecked the way that one can be: the map
|
|
198
|
+
* is conventional depth and the fold is the camera's reduction's, and getting either backwards
|
|
199
|
+
* keeps the nearest texel of a group — a caster hidden behind nothing, a shadow with a hole in it.
|
|
200
|
+
* So the arithmetic is one body and where the depth comes from is a prelude: the pass reads the
|
|
201
|
+
* map through `texture_depth_2d`, and `gpu-parity.mjs` runs the same body over an `r32float`
|
|
202
|
+
* texture, because a depth texture cannot be written by a copy and a harness can write that one.
|
|
203
|
+
*/
|
|
204
|
+
const SHADOW_HZB_SEED_BODY = `
|
|
205
|
+
/** The map's width and height. The base is half of each, as hzbMipSize says, and starts at zero. */
|
|
206
|
+
@group(0) @binding(0) var<storage, read> size: array<u32, 2>;
|
|
207
|
+
@group(0) @binding(2) var<storage, read_write> pyramid: array<f32>;
|
|
208
|
+
|
|
209
|
+
@compute @workgroup_size(8, 8)
|
|
210
|
+
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
211
|
+
let width = size[0];
|
|
212
|
+
let height = size[1];
|
|
213
|
+
let outWidth = max(1u, width / 2u);
|
|
214
|
+
let outHeight = max(1u, height / 2u);
|
|
215
|
+
if (id.x >= outWidth || id.y >= outHeight) { return; }
|
|
216
|
+
|
|
217
|
+
let x0 = id.x * 2u;
|
|
218
|
+
let y0 = id.y * 2u;
|
|
219
|
+
/* An odd map's extra row and column fold into the last group, as in HZB_REDUCE_WGSL. */
|
|
220
|
+
let lastX = select(min(width - 1u, x0 + 1u), width - 1u, id.x == outWidth - 1u);
|
|
221
|
+
let lastY = select(min(height - 1u, y0 + 1u), height - 1u, id.y == outHeight - 1u);
|
|
222
|
+
|
|
223
|
+
var deepest = -3.402823466e+38;
|
|
224
|
+
for (var sy = y0; sy <= lastY; sy = sy + 1u) {
|
|
225
|
+
for (var sx = x0; sx <= lastX; sx = sx + 1u) {
|
|
226
|
+
deepest = max(deepest, mapDepth(sx, sy));
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/* Turned over: the furthest of the group is now the smallest value, as the camera's is. */
|
|
230
|
+
pyramid[id.y * outWidth + id.x] = 1.0 - deepest;
|
|
231
|
+
}
|
|
232
|
+
`;
|
|
233
|
+
|
|
234
|
+
/** The light's pyramid's base, read from the shadow map itself. */
|
|
235
|
+
export const SHADOW_HZB_SEED_WGSL = `
|
|
236
|
+
@group(0) @binding(1) var depth: texture_depth_2d;
|
|
237
|
+
|
|
238
|
+
fn mapDepth(x: u32, y: u32) -> f32 {
|
|
239
|
+
return textureLoad(depth, vec2<i32>(i32(x), i32(y)), 0);
|
|
240
|
+
}
|
|
241
|
+
${SHADOW_HZB_SEED_BODY}`;
|
|
242
|
+
|
|
243
|
+
/** The same body over an `r32float` texture, for `gpu-parity.mjs`. */
|
|
244
|
+
export const SHADOW_HZB_SEED_FLOAT_WGSL = `
|
|
245
|
+
@group(0) @binding(1) var depth: texture_2d<f32>;
|
|
246
|
+
|
|
247
|
+
fn mapDepth(x: u32, y: u32) -> f32 {
|
|
248
|
+
return textureLoad(depth, vec2<i32>(i32(x), i32(y)), 0).r;
|
|
249
|
+
}
|
|
250
|
+
${SHADOW_HZB_SEED_BODY}`;
|
|
251
|
+
|
|
252
|
+
/** One reduction level of the hierarchical depth buffer. Mirrors `gpudriven/hzb.ts`. */
|
|
253
|
+
export const HZB_REDUCE_WGSL = `
|
|
254
|
+
/**
|
|
255
|
+
* srcWidth, srcHeight, where this level's source starts and where its output starts.
|
|
256
|
+
*
|
|
257
|
+
* **One binding for both halves, and it is a rule about scopes rather than a saving.** A buffer
|
|
258
|
+
* bound once as read-only and once as writable inside one compute pass is refused outright —
|
|
259
|
+
* "includes writable usage and another usage in the same synchronization scope" — and the whole
|
|
260
|
+
* pyramid lives in one buffer because CULL_CLUSTERS_WGSL reads every level through one binding and
|
|
261
|
+
* a levelStart table. So the reduction addresses both ends of its own copy itself. No backticks in
|
|
262
|
+
* here: one would close the template literal this shader is written in.
|
|
263
|
+
*/
|
|
264
|
+
@group(0) @binding(0) var<storage, read> size: array<u32, 4>;
|
|
265
|
+
@group(0) @binding(1) var<storage, read_write> pyramid: array<f32>;
|
|
266
|
+
|
|
267
|
+
@compute @workgroup_size(8, 8)
|
|
268
|
+
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
269
|
+
let width = size[0];
|
|
270
|
+
let height = size[1];
|
|
271
|
+
let srcStart = size[2];
|
|
272
|
+
let dstStart = size[3];
|
|
273
|
+
let outWidth = max(1u, width / 2u);
|
|
274
|
+
let outHeight = max(1u, height / 2u);
|
|
275
|
+
if (id.x >= outWidth || id.y >= outHeight) { return; }
|
|
276
|
+
|
|
277
|
+
let x0 = id.x * 2u;
|
|
278
|
+
let y0 = id.y * 2u;
|
|
279
|
+
let x1 = min(width - 1u, x0 + 1u);
|
|
280
|
+
let y1 = min(height - 1u, y0 + 1u);
|
|
281
|
+
/* An odd level's extra row and column fold into the last group rather than being dropped. */
|
|
282
|
+
let lastX = select(x1, width - 1u, id.x == outWidth - 1u);
|
|
283
|
+
let lastY = select(y1, height - 1u, id.y == outHeight - 1u);
|
|
284
|
+
|
|
285
|
+
var furthest = 3.402823466e+38;
|
|
286
|
+
for (var sy = y0; sy <= lastY; sy = sy + 1u) {
|
|
287
|
+
for (var sx = x0; sx <= lastX; sx = sx + 1u) {
|
|
288
|
+
/* Minimum, because reversed-Z puts the far plane at zero. Section 3 row 1. */
|
|
289
|
+
furthest = min(furthest, pyramid[srcStart + sy * width + sx]);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
pyramid[dstStart + id.y * outWidth + id.x] = furthest;
|
|
293
|
+
}
|
|
294
|
+
`;
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* The three cluster tests and the flag each writes. Mirrors `gpudriven/cullClusters.ts`.
|
|
298
|
+
*
|
|
299
|
+
* **One flag per invocation and no compaction here.** A dispatch can decide every cluster in
|
|
300
|
+
* parallel and cannot append them in input order without a prefix sum, so the ordered list is the
|
|
301
|
+
* host's — see the module's header. That also makes this checkable: a flag is order-free, so
|
|
302
|
+
* `gpu-parity.mjs` can compare it element by element without reproducing an atomic's arrival
|
|
303
|
+
* order, which is a thing no reference can do.
|
|
304
|
+
*
|
|
305
|
+
* `settings` carries the eye and the pyramid's shape rather than a second uniform block: three
|
|
306
|
+
* floats and four counts is smaller than the alignment rules for a struct would make it, and
|
|
307
|
+
* everything the harness binds is a plain array.
|
|
308
|
+
*
|
|
309
|
+
* **And whether to test cones at all**, in its ninth float. The visibility raster culls back faces,
|
|
310
|
+
* so a cluster whose every face points away draws nothing there and the cone test only saves the
|
|
311
|
+
* work. The blended raster draws both sides, so for its run the same answer would take the far face
|
|
312
|
+
* of every pane away — which the materials rig showed the day cones started working.
|
|
313
|
+
*
|
|
314
|
+
* **A cluster the cut did not select is not tested.** The compaction would drop it anyway; testing
|
|
315
|
+
* it was six planes, a cone and, in phase two, a walk of the pyramid for nothing — and it is how the
|
|
316
|
+
* instance cull reaches the clusters of a hidden mesh. That is the eighth binding, and the last a
|
|
317
|
+
* stage has by default.
|
|
318
|
+
*/
|
|
319
|
+
export const CULL_CLUSTERS_WGSL = `
|
|
320
|
+
@group(0) @binding(0) var<storage, read> planes: array<f32, 24>;
|
|
321
|
+
@group(0) @binding(1) var<storage, read> viewProj: array<f32, 16>;
|
|
322
|
+
/** eye.xyz, hasHzb, width, height, levelCount, clusterCount, testCones. */
|
|
323
|
+
@group(0) @binding(2) var<storage, read> settings: array<f32, ${CULL_SETTINGS_FLOATS}>;
|
|
324
|
+
@group(0) @binding(3) var<storage, read> clusters: array<f32>;
|
|
325
|
+
@group(0) @binding(4) var<storage, read> hzb: array<f32>;
|
|
326
|
+
@group(0) @binding(5) var<storage, read> levelStart: array<u32>;
|
|
327
|
+
@group(0) @binding(6) var<storage, read_write> keep: array<u32>;
|
|
328
|
+
/** The cut's flag a cluster, from LOD_CUT_WGSL. */
|
|
329
|
+
@group(0) @binding(7) var<storage, read> selected: array<u32>;
|
|
330
|
+
|
|
331
|
+
fn outsideFrustum(cx: f32, cy: f32, cz: f32, radius: f32) -> bool {
|
|
332
|
+
for (var p = 0u; p < 6u; p = p + 1u) {
|
|
333
|
+
let at = p * 4u;
|
|
334
|
+
let distance = planes[at] * cx + planes[at + 1u] * cy + planes[at + 2u] * cz + planes[at + 3u];
|
|
335
|
+
if (distance < -radius) { return true; }
|
|
336
|
+
}
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/* See coneBackfacing in cullClusters.ts: the cutoff is sin(a) and the radius term is the
|
|
341
|
+
sphere's own angular size. */
|
|
342
|
+
fn coneBackfacing(axis: vec3<f32>, cutoff: f32, centre: vec3<f32>, radius: f32, eye: vec3<f32>) -> bool {
|
|
343
|
+
let d = centre - eye;
|
|
344
|
+
return dot(d, axis) >= cutoff * length(d) + radius;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
@compute @workgroup_size(64)
|
|
348
|
+
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
349
|
+
let count = u32(settings[7]);
|
|
350
|
+
if (id.x >= count) { return; }
|
|
351
|
+
if (selected[id.x] == 0u) {
|
|
352
|
+
keep[id.x] = 0u;
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
let at = id.x * 8u;
|
|
356
|
+
let centre = vec3<f32>(clusters[at], clusters[at + 1u], clusters[at + 2u]);
|
|
357
|
+
let radius = clusters[at + 3u];
|
|
358
|
+
let axis = vec3<f32>(clusters[at + 4u], clusters[at + 5u], clusters[at + 6u]);
|
|
359
|
+
let cutoff = clusters[at + 7u];
|
|
360
|
+
let eye = vec3<f32>(settings[0], settings[1], settings[2]);
|
|
361
|
+
|
|
362
|
+
var survives = !outsideFrustum(centre.x, centre.y, centre.z, radius);
|
|
363
|
+
if (survives && settings[${CULL_CONES}] > 0.5) {
|
|
364
|
+
survives = !coneBackfacing(axis, cutoff, centre, radius, eye);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (survives && settings[3] > 0.5) {
|
|
368
|
+
/* The eight corners of the sphere's box, which is larger than the sphere and therefore
|
|
369
|
+
conservative. A corner at or behind the eye means there is no rectangle at all. */
|
|
370
|
+
var minX = 3.402823466e+38;
|
|
371
|
+
var minY = 3.402823466e+38;
|
|
372
|
+
var maxX = -3.402823466e+38;
|
|
373
|
+
var maxY = -3.402823466e+38;
|
|
374
|
+
var nearest = -3.402823466e+38;
|
|
375
|
+
var bounded = true;
|
|
376
|
+
for (var corner = 0u; corner < 8u; corner = corner + 1u) {
|
|
377
|
+
let p = vec3<f32>(
|
|
378
|
+
centre.x + select(-radius, radius, (corner & 1u) != 0u),
|
|
379
|
+
centre.y + select(-radius, radius, (corner & 2u) != 0u),
|
|
380
|
+
centre.z + select(-radius, radius, (corner & 4u) != 0u),
|
|
381
|
+
);
|
|
382
|
+
let cw = viewProj[3] * p.x + viewProj[7] * p.y + viewProj[11] * p.z + viewProj[15];
|
|
383
|
+
if (cw <= 1e-6) { bounded = false; }
|
|
384
|
+
let cx = viewProj[0] * p.x + viewProj[4] * p.y + viewProj[8] * p.z + viewProj[12];
|
|
385
|
+
let cy = viewProj[1] * p.x + viewProj[5] * p.y + viewProj[9] * p.z + viewProj[13];
|
|
386
|
+
let cz = viewProj[2] * p.x + viewProj[6] * p.y + viewProj[10] * p.z + viewProj[14];
|
|
387
|
+
let inv = 1.0 / cw;
|
|
388
|
+
let u = cx * inv * 0.5 + 0.5;
|
|
389
|
+
let v = cy * inv * 0.5 + 0.5;
|
|
390
|
+
minX = min(minX, u);
|
|
391
|
+
maxX = max(maxX, u);
|
|
392
|
+
minY = min(minY, v);
|
|
393
|
+
maxY = max(maxY, v);
|
|
394
|
+
/* Nearest is the largest clip depth: reversed-Z puts the near plane at one. */
|
|
395
|
+
nearest = max(nearest, cz * inv);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (bounded) {
|
|
399
|
+
let width = u32(settings[4]);
|
|
400
|
+
let height = u32(settings[5]);
|
|
401
|
+
let levels = u32(settings[6]);
|
|
402
|
+
let longest = max(max((maxX - minX) * f32(width), (maxY - minY) * f32(height)), 1.0);
|
|
403
|
+
let wanted = max(0.0, ceil(log2(longest)) - 1.0);
|
|
404
|
+
let top = floor(log2(max(1.0, f32(max(width, height)))));
|
|
405
|
+
let level = u32(min(wanted, top));
|
|
406
|
+
if (level < levels) {
|
|
407
|
+
let levelWidth = max(1u, width >> level);
|
|
408
|
+
let levelHeight = max(1u, height >> level);
|
|
409
|
+
let base = levelStart[level];
|
|
410
|
+
let x0 = u32(clamp(floor(minX * f32(levelWidth)), 0.0, f32(levelWidth - 1u)));
|
|
411
|
+
let x1 = u32(clamp(floor(maxX * f32(levelWidth)), 0.0, f32(levelWidth - 1u)));
|
|
412
|
+
/*
|
|
413
|
+
* The rows run the other way: the rectangle is in clip-up coordinates and the pyramid is
|
|
414
|
+
* seeded from the depth texture, whose row 0 is where clip y is +1. See clusterOccluded
|
|
415
|
+
* in cullClusters.ts, which carries what this cost before it was flipped.
|
|
416
|
+
*/
|
|
417
|
+
let y0 = u32(clamp(floor((1.0 - maxY) * f32(levelHeight)), 0.0, f32(levelHeight - 1u)));
|
|
418
|
+
let y1 = u32(clamp(floor((1.0 - minY) * f32(levelHeight)), 0.0, f32(levelHeight - 1u)));
|
|
419
|
+
var furthest = 3.402823466e+38;
|
|
420
|
+
for (var y = y0; y <= y1; y = y + 1u) {
|
|
421
|
+
for (var x = x0; x <= x1; x = x + 1u) {
|
|
422
|
+
/* The weakest of the group decides, so a gap in the occluder keeps the cluster. */
|
|
423
|
+
furthest = min(furthest, hzb[base + y * levelWidth + x]);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
if (nearest < furthest) { survives = false; }
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
keep[id.x] = select(0u, 1u, survives);
|
|
432
|
+
}
|
|
433
|
+
`;
|