@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,343 @@
|
|
|
1
|
+
import { GPU_DRIVEN_VERTEX_FLOATS } from '../../gpudriven/sceneUpload.ts';
|
|
2
|
+
import { DECODE_WGSL, decodeResourcesWgsl } from './decode.wgsl.ts';
|
|
3
|
+
import { ENVIRONMENT_WGSL } from './environment.wgsl.ts';
|
|
4
|
+
import { FOG_WGSL } from './fog.wgsl.ts';
|
|
5
|
+
import { FRAME_BLOCK_WGSL } from './frameBlock.wgsl.ts';
|
|
6
|
+
import { MATERIAL_SLOTS, MATERIAL_TABLE_WGSL } from './materialTable.wgsl.ts';
|
|
7
|
+
import { MESH_TRANSFORM_WGSL } from './meshTransform.wgsl.ts';
|
|
8
|
+
import { SHADE_LIGHTING_WGSL } from './shade.wgsl.ts';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The transparent half: one indirect draw, blended, shaded in the fragment stage.
|
|
12
|
+
*
|
|
13
|
+
* **A visibility buffer stores one surface a pixel and therefore cannot hold a blend at all.** That
|
|
14
|
+
* is architecture rather than an omission: the whole saving of the opaque path is that shading
|
|
15
|
+
* happens once per pixel, after the frame knows which triangle won, and a pane of glass has no
|
|
16
|
+
* winner. So the transparent set skips the visibility buffer and is drawn again here, shading where
|
|
17
|
+
* it stands, with the divergence that implies — exactly as every fragment on the forward path does.
|
|
18
|
+
*
|
|
19
|
+
* **What it reuses is the pipeline's front half.** `instanceCull` and the cut answer "which
|
|
20
|
+
* clusters, at which level of detail", and that question is the same for a pane as for a wall, so
|
|
21
|
+
* they run a second time over the other half of the scene rather than being written again. The
|
|
22
|
+
* material's blend flag is what the cut filters on; `cull.wgsl.ts` carries the filter.
|
|
23
|
+
*
|
|
24
|
+
* **It includes `SHADE_LIGHTING_WGSL` rather than restating it**, so the expression a pane of glass
|
|
25
|
+
* is lit by is the expression a wall is lit by, character for character. That is why the lighting
|
|
26
|
+
* was packaged as an includable function in the first place, and `scripts/gpu-parity.mjs` holds
|
|
27
|
+
* both to `gpudriven/lit.ts`.
|
|
28
|
+
*
|
|
29
|
+
* **Two targets and two blend states, both of which commute.** The accumulation sums weighted
|
|
30
|
+
* colour and the revealage multiplies what each layer let through, so the frame stops depending on
|
|
31
|
+
* which surface was submitted first. `orderIndependent.ts` is the arithmetic on the CPU and says
|
|
32
|
+
* what it approximates; `flatPass.ts`'s `oitTarget` is the same pair of blend states on the forward
|
|
33
|
+
* path. The weight is `oitWeight`, which both paths share.
|
|
34
|
+
*
|
|
35
|
+
* **Depth attached read-only.** A pane behind a wall is rejected at the wall, and nothing here
|
|
36
|
+
* writes depth, so two panes do not hide each other and there is something left to blend.
|
|
37
|
+
*
|
|
38
|
+
* **A transparent surface is not shadowed here**, which is the one place it is lit differently from
|
|
39
|
+
* an opaque one. `shadowFactor` wants a receiver plane, the shading pass derives one from
|
|
40
|
+
* barycentric gradients because a compute invocation has no neighbours, and a fragment stage would
|
|
41
|
+
* have to derive it another way — a second expression for a term whose whole point is that there is
|
|
42
|
+
* one. `docs/IMPROVEMENTS.md` carries the row. A pane in shadow therefore reads as a pane in
|
|
43
|
+
* sunlight, which is visible on a bright scene and is stated rather than hidden.
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* The weighted-transparency arithmetic, declared once for the three things that need it.
|
|
47
|
+
*
|
|
48
|
+
* **The blended raster, the resolve and the parity entry point are three readers of one rule**, and
|
|
49
|
+
* the first version of this file gave each of them its own copy. It was caught by the audit the
|
|
50
|
+
* plan asks for rather than by anything failing: perturbing the weight broke the check while the
|
|
51
|
+
* shader that draws the frame went on using the old one, which is the exact shape of a gate that
|
|
52
|
+
* watches a copy of the thing it is guarding.
|
|
53
|
+
*
|
|
54
|
+
* `render/orderIndependent.ts` is the reference all of this is written against — `oitWeight` and
|
|
55
|
+
* `resolveOit`, where both clamps are argued and the algebra is asserted against numbers — and
|
|
56
|
+
* `flat/main.ts` computes the same weight on the forward path.
|
|
57
|
+
*/
|
|
58
|
+
const OIT_WGSL = /* wgsl */ `
|
|
59
|
+
fn oitWeight(viewDepth: f32, alpha: f32) -> f32 {
|
|
60
|
+
let z = max(viewDepth, 0.0) / 200.0;
|
|
61
|
+
let falloff = 0.03 / (1e-5 + z * z * z * z);
|
|
62
|
+
return alpha * clamp(falloff, 1e-2, 3e3);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* Premultiplied and weighted, against a blend of "one, one": the target holds the two sums. */
|
|
66
|
+
fn oitAccumulate(colour: vec3<f32>, alpha: f32, weight: f32) -> vec4<f32> {
|
|
67
|
+
return vec4<f32>(colour * alpha * weight, alpha * weight);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/*
|
|
71
|
+
* The two targets, as a premultiplied fragment to lay over what is behind them.
|
|
72
|
+
*
|
|
73
|
+
* The weighted sum divided by the weighted alpha is the average colour the layers make, and the
|
|
74
|
+
* revealage says how much of the background still shows. The division is guarded because a pixel no
|
|
75
|
+
* fragment touched has a weighted alpha of zero — and its revealage of one discards whatever this
|
|
76
|
+
* produces anyway.
|
|
77
|
+
*/
|
|
78
|
+
fn oitResolved(accum: vec4<f32>, reveal: f32) -> vec4<f32> {
|
|
79
|
+
let average = accum.xyz / max(accum.w, 1e-5);
|
|
80
|
+
let covered = 1.0 - reveal;
|
|
81
|
+
return vec4<f32>(average * covered, covered);
|
|
82
|
+
}
|
|
83
|
+
`;
|
|
84
|
+
|
|
85
|
+
export const BLEND_RASTER_WGSL = /* wgsl */ `
|
|
86
|
+
struct BlendVarying {
|
|
87
|
+
@builtin(position) position: vec4<f32>,
|
|
88
|
+
@location(0) world: vec3<f32>,
|
|
89
|
+
@location(1) normal: vec3<f32>,
|
|
90
|
+
@location(2) colour: vec3<f32>,
|
|
91
|
+
@location(3) uv: vec2<f32>,
|
|
92
|
+
@location(4) @interpolate(flat) material: u32,
|
|
93
|
+
/* The vertex's own glow, added to the material's in the fragment as the shading pass adds it. */
|
|
94
|
+
@location(5) emissive: f32,
|
|
95
|
+
}
|
|
96
|
+
${MATERIAL_TABLE_WGSL}
|
|
97
|
+
${FRAME_BLOCK_WGSL}
|
|
98
|
+
@group(0) @binding(0) var<storage, read> viewProj: array<f32, 16>;
|
|
99
|
+
/** The compacted list of blended clusters, from the cut's second run. */
|
|
100
|
+
@group(0) @binding(1) var<storage, read> blendList: array<u32>;
|
|
101
|
+
@group(0) @binding(2) var<storage, read> clusterMeta: array<u32>;
|
|
102
|
+
@group(0) @binding(3) var<storage, read> indices: array<u32>;
|
|
103
|
+
@group(0) @binding(4) var<storage, read> vertices: array<f32>;
|
|
104
|
+
@group(0) @binding(5) var<storage, read> transforms: array<f32>;
|
|
105
|
+
@group(0) @binding(6) var<storage, read> materialOf: array<u32>;
|
|
106
|
+
@group(0) @binding(7) var<uniform> materials: array<Material, ${MATERIAL_SLOTS}>;
|
|
107
|
+
@group(0) @binding(8) var<uniform> frame: Frame;
|
|
108
|
+
@group(0) @binding(9) var environmentMap: texture_2d_array<f32>;
|
|
109
|
+
@group(0) @binding(10) var environmentSampler: sampler;
|
|
110
|
+
${decodeResourcesWgsl({ group: 0, latents: 11, clampSampler: 12, repeatSampler: 13, nodes: 14, weights: 15 })}
|
|
111
|
+
fn decodeLatentSize() -> f32 {
|
|
112
|
+
return frame.size.w;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
${DECODE_WGSL}
|
|
116
|
+
/*
|
|
117
|
+
* **Layer 0, which is this pipeline reading one probe of a grid**, and the same fetch
|
|
118
|
+
* shade.wgsl.ts makes for the same reason: what this pipeline owns is a fixed cluster set a few
|
|
119
|
+
* metres across, where a grid would pop as a surface crossed a cell.
|
|
120
|
+
*/
|
|
121
|
+
fn environmentSample(uv: vec2<f32>, level: f32) -> vec3<f32> {
|
|
122
|
+
return textureSampleLevel(environmentMap, environmentSampler, uv, 0, level).rgb;
|
|
123
|
+
}
|
|
124
|
+
${ENVIRONMENT_WGSL}
|
|
125
|
+
${MESH_TRANSFORM_WGSL}
|
|
126
|
+
${SHADE_LIGHTING_WGSL}
|
|
127
|
+
${FOG_WGSL}
|
|
128
|
+
${OIT_WGSL}
|
|
129
|
+
|
|
130
|
+
const NO_PROGRAM_HERE: u32 = ${0xffffffff}u;
|
|
131
|
+
|
|
132
|
+
/*
|
|
133
|
+
* The same fetch the visibility raster does, keeping the attributes instead of an identifier.
|
|
134
|
+
*
|
|
135
|
+
* **"metaAt", because "meta" is a reserved word in WGSL** — the visibility raster's own comment
|
|
136
|
+
* records that, and this shader indexes the same buffer the same way.
|
|
137
|
+
*/
|
|
138
|
+
@vertex
|
|
139
|
+
fn blendVert(
|
|
140
|
+
@builtin(vertex_index) vertex: u32,
|
|
141
|
+
@builtin(instance_index) slot: u32,
|
|
142
|
+
) -> BlendVarying {
|
|
143
|
+
var out: BlendVarying;
|
|
144
|
+
out.world = vec3<f32>(0.0);
|
|
145
|
+
out.normal = vec3<f32>(0.0, 1.0, 0.0);
|
|
146
|
+
out.colour = vec3<f32>(0.0);
|
|
147
|
+
out.uv = vec2<f32>(0.0);
|
|
148
|
+
out.material = 0u;
|
|
149
|
+
out.emissive = 0.0;
|
|
150
|
+
let cluster = blendList[slot];
|
|
151
|
+
let metaAt = cluster * 4u;
|
|
152
|
+
let indexOffset = clusterMeta[metaAt];
|
|
153
|
+
let indexCount = clusterMeta[metaAt + 1u];
|
|
154
|
+
let mesh = clusterMeta[metaAt + 3u];
|
|
155
|
+
|
|
156
|
+
let triangle = vertex / 3u;
|
|
157
|
+
/* Past this cluster's triangles: collapse to a point, which covers no pixel. */
|
|
158
|
+
if (triangle * 3u >= indexCount) {
|
|
159
|
+
out.position = vec4<f32>(0.0, 0.0, 0.0, 0.0);
|
|
160
|
+
return out;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
let index = indices[indexOffset + vertex];
|
|
164
|
+
let at = index * ${GPU_DRIVEN_VERTEX_FLOATS}u;
|
|
165
|
+
let local = vec3<f32>(vertices[at], vertices[at + 1u], vertices[at + 2u]);
|
|
166
|
+
let world = worldOf(mesh, local);
|
|
167
|
+
|
|
168
|
+
out.world = world;
|
|
169
|
+
out.normal = rotatedOf(mesh, vec3<f32>(vertices[at + 3u], vertices[at + 4u], vertices[at + 5u]));
|
|
170
|
+
out.colour = vec3<f32>(vertices[at + 6u], vertices[at + 7u], vertices[at + 8u]);
|
|
171
|
+
out.uv = vec2<f32>(vertices[at + 9u], vertices[at + 10u]);
|
|
172
|
+
out.emissive = vertices[at + 11u];
|
|
173
|
+
out.material = materialOf[cluster];
|
|
174
|
+
out.position = vec4<f32>(
|
|
175
|
+
viewProj[0] * world.x + viewProj[4] * world.y + viewProj[8] * world.z + viewProj[12],
|
|
176
|
+
viewProj[1] * world.x + viewProj[5] * world.y + viewProj[9] * world.z + viewProj[13],
|
|
177
|
+
viewProj[2] * world.x + viewProj[6] * world.y + viewProj[10] * world.z + viewProj[14],
|
|
178
|
+
viewProj[3] * world.x + viewProj[7] * world.y + viewProj[11] * world.z + viewProj[15],
|
|
179
|
+
);
|
|
180
|
+
return out;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
struct BlendTargets {
|
|
184
|
+
@location(0) accum: vec4<f32>,
|
|
185
|
+
@location(1) reveal: vec4<f32>,
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
@fragment
|
|
189
|
+
fn blendFrag(in: BlendVarying) -> BlendTargets {
|
|
190
|
+
var out: BlendTargets;
|
|
191
|
+
let entry = materials[min(in.material, ${MATERIAL_SLOTS - 1}u)];
|
|
192
|
+
let uv = in.uv * entry.maps.xy;
|
|
193
|
+
let lod = 0.0;
|
|
194
|
+
|
|
195
|
+
var baseColour = vec4<f32>(1.0);
|
|
196
|
+
if (entry.programs.x != NO_PROGRAM_HERE) {
|
|
197
|
+
baseColour = decodeProgram(entry.programs.x, uv, lod, frame.size.z);
|
|
198
|
+
}
|
|
199
|
+
/* The material's own opacity times whatever its base-colour map said about this texel. */
|
|
200
|
+
let alpha = clamp(entry.extra.x * baseColour.w, 0.0, 1.0);
|
|
201
|
+
let toEye = normalize(frame.eye.xyz - in.world);
|
|
202
|
+
|
|
203
|
+
var surface: LitSurface;
|
|
204
|
+
surface.albedo = in.colour * entry.tint.xyz * baseColour.xyz;
|
|
205
|
+
surface.normal = normalize(in.normal);
|
|
206
|
+
surface.toEye = toEye;
|
|
207
|
+
surface.roughness = entry.surface.x;
|
|
208
|
+
surface.specular = entry.surface.y;
|
|
209
|
+
surface.emissive = entry.tint.w + in.emissive;
|
|
210
|
+
/* Where the pane glows, as the shading pass decides it: the albedo times the emissive map. */
|
|
211
|
+
var emissiveMapped = vec3<f32>(1.0);
|
|
212
|
+
if (entry.programs.w != NO_PROGRAM_HERE) {
|
|
213
|
+
emissiveMapped = decodeProgram(entry.programs.w, uv, lod, frame.size.z).xyz;
|
|
214
|
+
}
|
|
215
|
+
surface.emissiveColour = surface.albedo * emissiveMapped;
|
|
216
|
+
/* Unshadowed, and the header says why and what it costs. */
|
|
217
|
+
surface.shade = 1.0;
|
|
218
|
+
surface.reflectivity = entry.surface.z;
|
|
219
|
+
surface.metalness = entry.surface.w;
|
|
220
|
+
surface.occlusion = 1.0;
|
|
221
|
+
|
|
222
|
+
var room: LitEnvironment;
|
|
223
|
+
room.lightDir = frame.lightDir.xyz;
|
|
224
|
+
room.lightColour = frame.lightColour.xyz;
|
|
225
|
+
room.sky = frame.sky.xyz;
|
|
226
|
+
room.ground = frame.ground.xyz;
|
|
227
|
+
let probeBound = frame.environment.w;
|
|
228
|
+
let edge = frame.environment.x;
|
|
229
|
+
let maxLod = frame.environment.y;
|
|
230
|
+
room.radiance = probeRadianceAt(reflect(-toEye, surface.normal), edge, clamp(entry.surface.x * maxLod, 0.0, maxLod), maxLod);
|
|
231
|
+
room.radianceAmount = probeBound;
|
|
232
|
+
room.irradiance = probeIrradianceAt(surface.normal, edge, frame.environment.z);
|
|
233
|
+
room.irradianceAmount = frame.environmentMix.x;
|
|
234
|
+
room.prefiltered = probeBound;
|
|
235
|
+
room.emission = frame.environmentMix.y;
|
|
236
|
+
|
|
237
|
+
/*
|
|
238
|
+
* **The haze multiplies the colour and not the alpha.** A pane at the render edge should take the
|
|
239
|
+
* haze's colour, not become more transparent: fogging its alpha would make distant glass vanish
|
|
240
|
+
* where it ought to grey out, and the two read completely differently across a large view
|
|
241
|
+
* distance — which is the whole reason this pipeline gained a fog.
|
|
242
|
+
*/
|
|
243
|
+
let toward = distance(in.world, frame.eye.xyz);
|
|
244
|
+
let colour = mix(litColour(surface, room), mediumColour(), mediumFog(toward, in.world.y));
|
|
245
|
+
|
|
246
|
+
/*
|
|
247
|
+
* **The distance to the eye, not the clip-space depth**, because that is what oitWeight's falloff
|
|
248
|
+
* is written in metres against — render/orderIndependent.ts divides by 200 and flat/main.ts takes
|
|
249
|
+
* "distance(vWorldPos, uCameraPos)". A weight fed a 0-to-1 depth instead would put every layer of
|
|
250
|
+
* every scene inside the first hundredth of the falloff.
|
|
251
|
+
*/
|
|
252
|
+
let weight = oitWeight(toward, alpha);
|
|
253
|
+
out.accum = oitAccumulate(colour, alpha, weight);
|
|
254
|
+
/* One channel, and it multiplies: what this layer let through. See the blend state. */
|
|
255
|
+
out.reveal = vec4<f32>(alpha, 0.0, 0.0, alpha);
|
|
256
|
+
return out;
|
|
257
|
+
}
|
|
258
|
+
`;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* The two targets composited over what the opaque half drew.
|
|
262
|
+
*
|
|
263
|
+
* **`resolveOit` in `render/orderIndependent.ts`, transcribed**, and the division's guard is that
|
|
264
|
+
* file's: a pixel no fragment touched has a weighted alpha of zero, and its revealage of one
|
|
265
|
+
* discards whatever this produced anyway.
|
|
266
|
+
*
|
|
267
|
+
* **Premultiplied, where the forward path's composite is a lerp**, and the difference is what the
|
|
268
|
+
* alpha channel means on each side. `renderer.ts` resolves over a scene target whose alpha is not a
|
|
269
|
+
* coverage mask; this pipeline's colour target has one, because the blit reads it to decide whether
|
|
270
|
+
* the pass drew a pixel at all. Writing `average * (1 - reveal)` with `1 - reveal` in alpha and
|
|
271
|
+
* blending `(one, one-minus-src-alpha)` gives both at once: the colour is the same lerp, and the
|
|
272
|
+
* coverage becomes `1 - (1 - covered) * reveal` — so a pane over empty sky marks the pixel as
|
|
273
|
+
* drawn, which a lerp would not have.
|
|
274
|
+
*/
|
|
275
|
+
export const BLEND_RESOLVE_WGSL = /* wgsl */ `
|
|
276
|
+
@group(0) @binding(0) var accumMap: texture_2d<f32>;
|
|
277
|
+
@group(0) @binding(1) var revealMap: texture_2d<f32>;
|
|
278
|
+
${OIT_WGSL}
|
|
279
|
+
|
|
280
|
+
struct Corner {
|
|
281
|
+
@builtin(position) position: vec4<f32>,
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
@vertex
|
|
285
|
+
fn resolveVert(@builtin(vertex_index) vertex: u32) -> Corner {
|
|
286
|
+
/* One triangle covering the target, which needs no vertex buffer and no clip correction. */
|
|
287
|
+
var out: Corner;
|
|
288
|
+
let x = f32((vertex << 1u) & 2u) * 2.0 - 1.0;
|
|
289
|
+
let y = f32(vertex & 2u) * 2.0 - 1.0;
|
|
290
|
+
out.position = vec4<f32>(x, y, 0.0, 1.0);
|
|
291
|
+
return out;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
@fragment
|
|
295
|
+
fn resolveFrag(in: Corner) -> @location(0) vec4<f32> {
|
|
296
|
+
let at = vec2<u32>(in.position.xy);
|
|
297
|
+
let accum = textureLoad(accumMap, at, 0);
|
|
298
|
+
let reveal = textureLoad(revealMap, at, 0).x;
|
|
299
|
+
return oitResolved(accum, reveal);
|
|
300
|
+
}
|
|
301
|
+
`;
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* The weight and the resolve alone, as a dispatch, so both can be checked against the reference.
|
|
305
|
+
*
|
|
306
|
+
* **What a picture cannot show is whether the weight is the forward path's.** Two panes blended by
|
|
307
|
+
* a weight twice as steep still look like two panes; what it changes is how much a far layer keeps,
|
|
308
|
+
* and nothing about the frame says so. So the arithmetic is lifted out and compared against
|
|
309
|
+
* `oitWeight` and `resolveOit` over generated cases.
|
|
310
|
+
*/
|
|
311
|
+
export const BLEND_OIT_PARITY_WGSL = /* wgsl */ `
|
|
312
|
+
/** Six floats a case: depth, alpha, colour, and the background behind it. */
|
|
313
|
+
@group(0) @binding(0) var<storage, read> cases: array<f32>;
|
|
314
|
+
/** Four out: the weight, and the three resolved channels. */
|
|
315
|
+
@group(0) @binding(1) var<storage, read_write> results: array<f32>;
|
|
316
|
+
${OIT_WGSL}
|
|
317
|
+
@compute @workgroup_size(64)
|
|
318
|
+
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
319
|
+
if (id.x * 8u + 7u >= arrayLength(&cases)) { return; }
|
|
320
|
+
let at = id.x * 8u;
|
|
321
|
+
let depth = cases[at];
|
|
322
|
+
let alpha = cases[at + 1u];
|
|
323
|
+
let colour = vec3<f32>(cases[at + 2u], cases[at + 3u], cases[at + 4u]);
|
|
324
|
+
let background = vec3<f32>(cases[at + 5u], cases[at + 6u], cases[at + 7u]);
|
|
325
|
+
|
|
326
|
+
let weight = oitWeight(depth, alpha);
|
|
327
|
+
/* One fragment folded in, which is the anchor: for a single layer this reduces to "over". */
|
|
328
|
+
let accum = oitAccumulate(colour, alpha, weight);
|
|
329
|
+
let reveal = 1.0 - alpha;
|
|
330
|
+
/*
|
|
331
|
+
* The resolve's own fragment, then the blend state applied by hand: the pipeline lays it over
|
|
332
|
+
* the target with "one, one-minus-src-alpha", so the background keeps the revealage.
|
|
333
|
+
*/
|
|
334
|
+
let over = oitResolved(accum, reveal);
|
|
335
|
+
let resolved = over.xyz + background * (1.0 - over.w);
|
|
336
|
+
|
|
337
|
+
let out = id.x * 4u;
|
|
338
|
+
results[out] = weight;
|
|
339
|
+
results[out + 1u] = resolved.x;
|
|
340
|
+
results[out + 2u] = resolved.y;
|
|
341
|
+
results[out + 3u] = resolved.z;
|
|
342
|
+
}
|
|
343
|
+
`;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Three flag buffers into one list, and the block that draws it.
|
|
3
|
+
*
|
|
4
|
+
* **Hand-written WGSL for the reason `cull.wgsl.ts` gives**: there is no GLSL original, because
|
|
5
|
+
* WebGL2 has neither a compute stage nor an indirect draw. What keeps it honest is
|
|
6
|
+
* `scripts/gpu-parity.mjs`, which runs it against `gpudriven/compact.ts` over generated flags.
|
|
7
|
+
*
|
|
8
|
+
* **The atomic is the whole of it and it is on the draw block rather than on a counter beside
|
|
9
|
+
* it.** `instanceCount` is the number of clusters this phase draws; incrementing it *is* claiming
|
|
10
|
+
* a slot in the list, so a separate counter would be the same number in two places and the block
|
|
11
|
+
* would be written by whoever remembered. The other three words never change — the vertex count is
|
|
12
|
+
* a cluster's index cap and the two firsts are zero — so a caller writes them once at creation and
|
|
13
|
+
* clears the one word a frame.
|
|
14
|
+
*
|
|
15
|
+
* **Which phase is a setting rather than two shaders.** The two differ only in which side of the
|
|
16
|
+
* history they take, and a second entry point would be a second place for the cut and the cull to
|
|
17
|
+
* be applied — which is the half that must be identical in both. See `compact.ts` for the
|
|
18
|
+
* invariant this is obeying: the history decides which phase a cluster is judged in and never
|
|
19
|
+
* whether it is judged.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* One invocation a cluster.
|
|
24
|
+
*
|
|
25
|
+
* `settings` is the phase — 0 for the half the history holds, 1 for the rest — and the cluster
|
|
26
|
+
* count. `drawn` is next frame's history and **only phase two writes it**, for every cluster it
|
|
27
|
+
* keeps whichever half judged it, because only phase two's cull has seen this frame's pyramid; see
|
|
28
|
+
* `compactPhase` in `compact.ts`. A caller clears it once a frame.
|
|
29
|
+
*/
|
|
30
|
+
export const COMPACT_CLUSTERS_WGSL = `
|
|
31
|
+
/** phase, clusterCount. */
|
|
32
|
+
@group(0) @binding(0) var<storage, read> settings: array<u32, 2>;
|
|
33
|
+
@group(0) @binding(1) var<storage, read> selected: array<u32>;
|
|
34
|
+
@group(0) @binding(2) var<storage, read> keep: array<u32>;
|
|
35
|
+
@group(0) @binding(3) var<storage, read> history: array<u32>;
|
|
36
|
+
@group(0) @binding(4) var<storage, read_write> list: array<u32>;
|
|
37
|
+
@group(0) @binding(5) var<storage, read_write> drawn: array<u32>;
|
|
38
|
+
/** A four-word non-indexed draw block. Only word one is touched here; see the header. */
|
|
39
|
+
@group(0) @binding(6) var<storage, read_write> args: array<atomic<u32>>;
|
|
40
|
+
|
|
41
|
+
@compute @workgroup_size(64)
|
|
42
|
+
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
43
|
+
if (id.x >= settings[1]) { return; }
|
|
44
|
+
|
|
45
|
+
let seen = history[id.x] != 0u;
|
|
46
|
+
let phaseOne = settings[0] == 0u;
|
|
47
|
+
let visible = selected[id.x] != 0u && keep[id.x] != 0u;
|
|
48
|
+
/* Next frame's history is phase two's answer, for the clusters phase one drew as well. */
|
|
49
|
+
if (!phaseOne && visible) { drawn[id.x] = 1u; }
|
|
50
|
+
|
|
51
|
+
/* The history decides which half judges this cluster, never whether one does. */
|
|
52
|
+
if (seen != phaseOne || !visible) { return; }
|
|
53
|
+
|
|
54
|
+
/* Claiming the slot and counting the instance are one operation, which is why the atomic is on
|
|
55
|
+
the draw block. The order slots are handed out in is the scheduler's and is not an answer. */
|
|
56
|
+
let slot = atomicAdd(&args[1], 1u);
|
|
57
|
+
list[slot] = id.x;
|
|
58
|
+
}
|
|
59
|
+
`;
|