@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,493 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A few probes a frame, traced down the GI chain and convolved into the grid the shading samples.
|
|
3
|
+
*
|
|
4
|
+
* **The light arrives through `gridIrradiance` and nowhere else**, which is Wave 4A's own
|
|
5
|
+
* constraint: a second per-pixel irradiance buffer beside the one the shading already mixes into
|
|
6
|
+
* its ambient is a design failure rather than an optimisation. So this writes the *irradiance level
|
|
7
|
+
* of the existing probe array* — the same texels a rasterised bake would have written — and the lit
|
|
8
|
+
* pass changes not at all.
|
|
9
|
+
*
|
|
10
|
+
* **Three steps on one encoder, in order.** A compute dispatch traces `PROBE_DIRECTIONS` rays for
|
|
11
|
+
* each scheduled probe; a second convolves those rays into an octahedral map; a render pass a layer
|
|
12
|
+
* carries the map into the array. They are separate because the convolution reads every ray of its
|
|
13
|
+
* probe, so tracing per texel would cast the same rays `edge²` times.
|
|
14
|
+
*
|
|
15
|
+
* **The array is sampled by the first step and written by the third, and that is legal.** WebGPU
|
|
16
|
+
* forbids a texture being read and written inside one pass, not across passes on one encoder. What
|
|
17
|
+
* it costs is a frame of latency in the bounce, which a probe volume has anyway because it
|
|
18
|
+
* accumulates — and the accumulation is what makes the solution multi-bounce.
|
|
19
|
+
*
|
|
20
|
+
* **The grid does not have to be seeded, and two wrong diagnoses said it did.** A traced probe
|
|
21
|
+
* gathers radiance from the field it hits and reads what that surface is worth *from the probes* —
|
|
22
|
+
* the maintainer's answer of 2026-09-17, and what makes the solution converge on several bounces.
|
|
23
|
+
* Since Task 8 it also evaluates the *sun* at the hit, so it introduces light of its own and a grid
|
|
24
|
+
* starting at black climbs away from black. It is not a fixed point.
|
|
25
|
+
*
|
|
26
|
+
* It looked like one twice. `demo/dev/bounce.html` with no rasterised capture came back at a
|
|
27
|
+
* uniform 209 of 255, first read as "converges on whatever it started with" and then as undefined
|
|
28
|
+
* memory in the probe array. It was neither: `flatTextures` resolves `uEnvironment` to a one-texel
|
|
29
|
+
* **white** stand-in while `probeBaked` is false, and a flat bind group holds whatever texture
|
|
30
|
+
* existed when it was built — so a renderer whose grid is filled by tracing kept that white for
|
|
31
|
+
* ever, and 209 is 0.82 (the room's albedo) times 255. `markProbeFilled` rebuilds the groups when
|
|
32
|
+
* the last layer lands, and the room now measures the same with the capture and without it.
|
|
33
|
+
*
|
|
34
|
+
* So `bakeProbeGrid` is an optional head start rather than a requirement, and **the wave's
|
|
35
|
+
* criterion of "no baked lighting" is met literally**: `scripts/bounce-check.mjs` runs the page
|
|
36
|
+
* with `?seed=0` and asserts it.
|
|
37
|
+
*
|
|
38
|
+
* **A layer nothing has ever rasterised gets its whole chain written once**, because the roughness
|
|
39
|
+
* levels of an unseeded array hold undefined contents and a reflective surface sampling those is
|
|
40
|
+
* worse than one sampling a flat colour. A seeded layer keeps the chain it was given and only its
|
|
41
|
+
* irradiance level is rewritten, which is the level the diffuse term reads.
|
|
42
|
+
*/
|
|
43
|
+
import { PROBE_DIRECTIONS } from '../../gi/probeTrace.js';
|
|
44
|
+
import { probeUpdateSchedule } from '../../gi/probeVolume.js';
|
|
45
|
+
import { irradianceLevelFor } from '../../prefilterEnvMap.js';
|
|
46
|
+
import { BAKE_COUNTS, BAKE_EDGE, BAKE_FRAME, BAKE_ORIGIN, BAKE_SCHEDULED, BAKE_SPACING, BAKE_SKY_COLOUR, BAKE_SUN_COLOUR, BAKE_SUN_DIR, PROBE_BAKE_FLOATS, PROBE_BAKE_WORKGROUP, PROBE_BLIT_FLOATS, PROBE_BLIT_STRIDE, PROBE_BLIT_WGSL, PROBE_RAY_FLOATS, PROBE_TEXEL_FLOATS, probeBakeWgsl, } from '../../shaders/gi/probeBake.wgsl.js';
|
|
47
|
+
import { PROBE_MARCH_DEFAULTS, PROBE_MARCH_FLOATS } from '../../shaders/gi/probeTrace.wgsl.js';
|
|
48
|
+
import { PROBE_VOLUME_FLOATS, VOLUME_COUNTS, VOLUME_EDGE, VOLUME_INV_SPACING, VOLUME_LEVEL, VOLUME_ORIGIN, VOLUME_RADIANCE_EDGE, VOLUME_RADIANCE_LEVEL, } from '../../shaders/gi/probeVolume.wgsl.js';
|
|
49
|
+
const COPY_DST = 0x0008;
|
|
50
|
+
const COPY_SRC = 0x0004;
|
|
51
|
+
const MAP_READ = 0x0001;
|
|
52
|
+
const QUERY_RESOLVE = 0x0200;
|
|
53
|
+
const STORAGE = 0x0080;
|
|
54
|
+
const UNIFORM = 0x0040;
|
|
55
|
+
const VISIBILITY_FRAGMENT = 0x2;
|
|
56
|
+
const VISIBILITY_COMPUTE = 0x4;
|
|
57
|
+
/**
|
|
58
|
+
* How many probes are refreshed a frame.
|
|
59
|
+
*
|
|
60
|
+
* **Five, and the number is a cost rather than a quality.** Each is `PROBE_DIRECTIONS` marches down
|
|
61
|
+
* a three-level chain, and what makes a probe converge is the direction set turning between
|
|
62
|
+
* refreshes rather than any single refresh being final. A 64-probe grid comes all the way round in
|
|
63
|
+
* thirteen frames, which at sixty a second is a fifth of a second for a light that moved.
|
|
64
|
+
*/
|
|
65
|
+
export const PROBES_PER_FRAME = 5;
|
|
66
|
+
export class ProbeBaker {
|
|
67
|
+
device;
|
|
68
|
+
targets;
|
|
69
|
+
/** Which mip holds the cosine convolution, and how many texels across it is. */
|
|
70
|
+
level;
|
|
71
|
+
levelEdge;
|
|
72
|
+
texels;
|
|
73
|
+
tracePipeline;
|
|
74
|
+
convolvePipeline;
|
|
75
|
+
blitPipeline;
|
|
76
|
+
computeLayout;
|
|
77
|
+
marchBuffer;
|
|
78
|
+
bakeBuffer;
|
|
79
|
+
volumeBuffer;
|
|
80
|
+
scheduleBuffer;
|
|
81
|
+
rayBuffer;
|
|
82
|
+
irradianceBuffer;
|
|
83
|
+
blitParams;
|
|
84
|
+
blitGroup;
|
|
85
|
+
/** Rebuilt only when the field it was built against is a different object. */
|
|
86
|
+
computeGroup = null;
|
|
87
|
+
boundTo = null;
|
|
88
|
+
marchScratch = new Float32Array(PROBE_MARCH_FLOATS);
|
|
89
|
+
marchInts = new Uint32Array(this.marchScratch.buffer);
|
|
90
|
+
bakeScratch = new Float32Array(PROBE_BAKE_FLOATS);
|
|
91
|
+
volumeScratch = new Float32Array(PROBE_VOLUME_FLOATS);
|
|
92
|
+
scheduleScratch = new Int32Array(PROBES_PER_FRAME);
|
|
93
|
+
scheduleUpload = new Uint32Array(PROBES_PER_FRAME);
|
|
94
|
+
/** One view a layer a level, built when the grid changes rather than in the frame loop. */
|
|
95
|
+
views = [];
|
|
96
|
+
/** Which layers have had their whole chain written, so the first fill happens once. */
|
|
97
|
+
filled = new Uint8Array(0);
|
|
98
|
+
layers = 0;
|
|
99
|
+
frameIndex = 0;
|
|
100
|
+
/**
|
|
101
|
+
* The device's own clock around the two dispatches, where it has one.
|
|
102
|
+
*
|
|
103
|
+
* **Beside the work it measures, exactly as `FieldComposer`'s is.** Without it the only figure
|
|
104
|
+
* indirect light could publish was the *composition's*, and the trace — which is the half the
|
|
105
|
+
* feature is named for — had no cost anyone could quote. The blits are outside the pair
|
|
106
|
+
* deliberately: they are render passes an encoder interleaves with the frame's own, and a span
|
|
107
|
+
* that covered them would be measuring the frame rather than the bake.
|
|
108
|
+
*/
|
|
109
|
+
queries;
|
|
110
|
+
queryResolve;
|
|
111
|
+
queryRead;
|
|
112
|
+
queryCopied = false;
|
|
113
|
+
queryMapping = false;
|
|
114
|
+
timed = false;
|
|
115
|
+
bakeMsValue = 0;
|
|
116
|
+
constructor(device, targets) {
|
|
117
|
+
this.device = device;
|
|
118
|
+
this.targets = targets;
|
|
119
|
+
this.level = irradianceLevelFor(targets.edge);
|
|
120
|
+
this.levelEdge = Math.max(1, targets.edge >> this.level);
|
|
121
|
+
this.texels = this.levelEdge * this.levelEdge;
|
|
122
|
+
const module = device.createShaderModule({ label: 'probe bake', code: probeBakeWgsl() });
|
|
123
|
+
/*
|
|
124
|
+
* **One explicit layout for both dispatches, and `'auto'` cannot do it.** An auto-generated
|
|
125
|
+
* layout belongs to the pipeline that generated it and is compatible with no other, so a bind
|
|
126
|
+
* group built from the trace pipeline's would be rejected by the convolve pipeline — two
|
|
127
|
+
* entry points of the same module over exactly the same bindings. Written out, one group
|
|
128
|
+
* serves both, and there is one place a binding number can be wrong rather than two.
|
|
129
|
+
*/
|
|
130
|
+
const storageRead = { type: 'read-only-storage' };
|
|
131
|
+
this.computeLayout = device.createBindGroupLayout({
|
|
132
|
+
label: 'probe bake.layout',
|
|
133
|
+
entries: [
|
|
134
|
+
{ binding: 0, visibility: VISIBILITY_COMPUTE, buffer: storageRead },
|
|
135
|
+
{ binding: 1, visibility: VISIBILITY_COMPUTE, buffer: storageRead },
|
|
136
|
+
{ binding: 2, visibility: VISIBILITY_COMPUTE, buffer: { type: 'uniform' } },
|
|
137
|
+
{ binding: 3, visibility: VISIBILITY_COMPUTE, buffer: { type: 'uniform' } },
|
|
138
|
+
{ binding: 4, visibility: VISIBILITY_COMPUTE, buffer: storageRead },
|
|
139
|
+
{ binding: 5, visibility: VISIBILITY_COMPUTE, buffer: { type: 'storage' } },
|
|
140
|
+
{ binding: 6, visibility: VISIBILITY_COMPUTE, buffer: { type: 'storage' } },
|
|
141
|
+
{ binding: 7, visibility: VISIBILITY_COMPUTE, buffer: { type: 'uniform' } },
|
|
142
|
+
{
|
|
143
|
+
binding: 8,
|
|
144
|
+
visibility: VISIBILITY_COMPUTE,
|
|
145
|
+
texture: { sampleType: 'float', viewDimension: '2d-array' },
|
|
146
|
+
},
|
|
147
|
+
{ binding: 9, visibility: VISIBILITY_COMPUTE, sampler: { type: 'filtering' } },
|
|
148
|
+
{ binding: 10, visibility: VISIBILITY_COMPUTE, buffer: storageRead },
|
|
149
|
+
],
|
|
150
|
+
});
|
|
151
|
+
const computeLayout = device.createPipelineLayout({
|
|
152
|
+
bindGroupLayouts: [this.computeLayout],
|
|
153
|
+
});
|
|
154
|
+
this.tracePipeline = device.createComputePipeline({
|
|
155
|
+
label: 'probe bake trace',
|
|
156
|
+
layout: computeLayout,
|
|
157
|
+
compute: { module, entryPoint: 'traceMain' },
|
|
158
|
+
});
|
|
159
|
+
this.convolvePipeline = device.createComputePipeline({
|
|
160
|
+
label: 'probe bake convolve',
|
|
161
|
+
layout: computeLayout,
|
|
162
|
+
compute: { module, entryPoint: 'convolveMain' },
|
|
163
|
+
});
|
|
164
|
+
const blit = device.createShaderModule({ label: 'probe blit', code: PROBE_BLIT_WGSL });
|
|
165
|
+
/*
|
|
166
|
+
* **An explicit layout rather than `'auto'`, because the parameters are read by dynamic
|
|
167
|
+
* offset.** An inferred layout declares `hasDynamicOffset: false`, so `setBindGroup` with an
|
|
168
|
+
* offset is rejected — and the alternative is a bind group a draw, which is the per-frame
|
|
169
|
+
* allocation the house rules are about. `filmPass.ts` writes the same layout for the same
|
|
170
|
+
* reason.
|
|
171
|
+
*/
|
|
172
|
+
const blitLayout = device.createBindGroupLayout({
|
|
173
|
+
label: 'probe blit.layout',
|
|
174
|
+
entries: [
|
|
175
|
+
{
|
|
176
|
+
binding: 0,
|
|
177
|
+
visibility: VISIBILITY_FRAGMENT,
|
|
178
|
+
buffer: {
|
|
179
|
+
type: 'uniform',
|
|
180
|
+
hasDynamicOffset: true,
|
|
181
|
+
minBindingSize: PROBE_BLIT_FLOATS * 4,
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
binding: 1,
|
|
186
|
+
visibility: VISIBILITY_FRAGMENT,
|
|
187
|
+
buffer: { type: 'read-only-storage' },
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
});
|
|
191
|
+
this.blitPipeline = device.createRenderPipeline({
|
|
192
|
+
label: 'probe blit',
|
|
193
|
+
layout: device.createPipelineLayout({ bindGroupLayouts: [blitLayout] }),
|
|
194
|
+
vertex: { module: blit, entryPoint: 'blitVert' },
|
|
195
|
+
fragment: {
|
|
196
|
+
module: blit,
|
|
197
|
+
entryPoint: 'blitFrag',
|
|
198
|
+
targets: [{ format: targets.format }],
|
|
199
|
+
},
|
|
200
|
+
primitive: { topology: 'triangle-list' },
|
|
201
|
+
});
|
|
202
|
+
this.marchBuffer = this.uniform('march', PROBE_MARCH_FLOATS * 4);
|
|
203
|
+
this.bakeBuffer = this.uniform('bake', PROBE_BAKE_FLOATS * 4);
|
|
204
|
+
this.volumeBuffer = this.uniform('volume', PROBE_VOLUME_FLOATS * 4);
|
|
205
|
+
this.scheduleBuffer = this.storage('schedule', PROBES_PER_FRAME * 4);
|
|
206
|
+
this.rayBuffer = this.storage('rays', PROBES_PER_FRAME * PROBE_DIRECTIONS * PROBE_RAY_FLOATS * 4);
|
|
207
|
+
this.irradianceBuffer = this.storage('irradiance', PROBES_PER_FRAME * this.texels * PROBE_TEXEL_FLOATS * 4);
|
|
208
|
+
/*
|
|
209
|
+
* **The blit's parameters are written once and read by dynamic offset**, because a slot's
|
|
210
|
+
* number never changes: slot 0 is always slot 0. Building a bind group a draw would be the
|
|
211
|
+
* per-frame allocation the house rules are about, and a uniform rewritten between draws would
|
|
212
|
+
* give every draw the last write — the hazard `FieldComposer` documents for its cascades.
|
|
213
|
+
*/
|
|
214
|
+
this.blitParams = this.device.createBuffer({
|
|
215
|
+
label: 'probe blit params',
|
|
216
|
+
size: PROBES_PER_FRAME * (this.level + 1) * PROBE_BLIT_STRIDE,
|
|
217
|
+
usage: UNIFORM | COPY_DST,
|
|
218
|
+
});
|
|
219
|
+
const params = new Float32Array(PROBE_BLIT_FLOATS);
|
|
220
|
+
for (let slot = 0; slot < PROBES_PER_FRAME; slot += 1) {
|
|
221
|
+
for (let level = 0; level <= this.level; level += 1) {
|
|
222
|
+
params[0] = slot;
|
|
223
|
+
params[1] = this.levelEdge;
|
|
224
|
+
params[2] = Math.max(1, targets.edge >> level);
|
|
225
|
+
device.queue.writeBuffer(this.blitParams, this.blitOffset(slot, level), params);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
this.blitGroup = device.createBindGroup({
|
|
229
|
+
label: 'probe blit',
|
|
230
|
+
layout: blitLayout,
|
|
231
|
+
entries: [
|
|
232
|
+
{
|
|
233
|
+
binding: 0,
|
|
234
|
+
resource: {
|
|
235
|
+
buffer: this.blitParams,
|
|
236
|
+
offset: 0,
|
|
237
|
+
size: PROBE_BLIT_FLOATS * 4,
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
{ binding: 1, resource: { buffer: this.irradianceBuffer } },
|
|
241
|
+
],
|
|
242
|
+
});
|
|
243
|
+
const clocked = device.features.has('timestamp-query');
|
|
244
|
+
this.queries = clocked
|
|
245
|
+
? device.createQuerySet({ label: 'probe bake timings', type: 'timestamp', count: 2 })
|
|
246
|
+
: null;
|
|
247
|
+
this.queryResolve = clocked
|
|
248
|
+
? device.createBuffer({
|
|
249
|
+
label: 'probe bake timings resolve',
|
|
250
|
+
size: 16,
|
|
251
|
+
usage: QUERY_RESOLVE | COPY_SRC,
|
|
252
|
+
})
|
|
253
|
+
: null;
|
|
254
|
+
this.queryRead = clocked
|
|
255
|
+
? device.createBuffer({
|
|
256
|
+
label: 'probe bake timings read',
|
|
257
|
+
size: 16,
|
|
258
|
+
usage: COPY_DST | MAP_READ,
|
|
259
|
+
})
|
|
260
|
+
: null;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* The device milliseconds the last measured bake took, or null where nothing measured it.
|
|
264
|
+
*
|
|
265
|
+
* One frame behind, because a timestamp is read back and a readback that blocked would be the
|
|
266
|
+
* measurement changing what it measures. It covers one refresh — `PROBES_PER_FRAME` probes —
|
|
267
|
+
* rather than a whole grid, which is what a frame actually pays.
|
|
268
|
+
*/
|
|
269
|
+
get bakeMs() {
|
|
270
|
+
return this.timed ? this.bakeMsValue : null;
|
|
271
|
+
}
|
|
272
|
+
/** Ask for the last frame's figure, once the frame that recorded it has been submitted. */
|
|
273
|
+
readTimings() {
|
|
274
|
+
if (this.queryRead === null || !this.queryCopied || this.queryMapping)
|
|
275
|
+
return;
|
|
276
|
+
this.queryMapping = true;
|
|
277
|
+
const buffer = this.queryRead;
|
|
278
|
+
void buffer
|
|
279
|
+
.mapAsync(MAP_READ)
|
|
280
|
+
.then(() => {
|
|
281
|
+
const stamps = new BigUint64Array(buffer.getMappedRange().slice(0));
|
|
282
|
+
buffer.unmap();
|
|
283
|
+
const from = stamps[0] ?? 0n;
|
|
284
|
+
const to = stamps[1] ?? 0n;
|
|
285
|
+
/* Nanoseconds, and a pair that never ran reads zero rather than a negative span. */
|
|
286
|
+
this.bakeMsValue = to > from ? Number(to - from) / 1e6 : 0;
|
|
287
|
+
this.timed = true;
|
|
288
|
+
})
|
|
289
|
+
.catch(() => {
|
|
290
|
+
/* A device that will not map its own query buffer reports no timing and bakes anyway. */
|
|
291
|
+
})
|
|
292
|
+
.finally(() => {
|
|
293
|
+
this.queryMapping = false;
|
|
294
|
+
this.queryCopied = false;
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
blitOffset(slot, level) {
|
|
298
|
+
return (slot * (this.level + 1) + level) * PROBE_BLIT_STRIDE;
|
|
299
|
+
}
|
|
300
|
+
uniform(label, bytes) {
|
|
301
|
+
return this.device.createBuffer({
|
|
302
|
+
label: `probe bake ${label}`,
|
|
303
|
+
size: Math.max(16, Math.ceil(bytes / 16) * 16),
|
|
304
|
+
usage: UNIFORM | COPY_DST,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
storage(label, bytes) {
|
|
308
|
+
return this.device.createBuffer({
|
|
309
|
+
label: `probe bake ${label}`,
|
|
310
|
+
size: Math.max(4, bytes),
|
|
311
|
+
usage: STORAGE | COPY_DST,
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Build the per-layer views a grid needs, and forget which layers were filled.
|
|
316
|
+
*
|
|
317
|
+
* Called when the grid changes rather than every frame: a view is cheap and sixty-four of them
|
|
318
|
+
* are not, and the frame path is the one place this project does not allocate.
|
|
319
|
+
*/
|
|
320
|
+
setGrid(layers) {
|
|
321
|
+
if (layers === this.layers && this.views.length === layers)
|
|
322
|
+
return;
|
|
323
|
+
this.layers = layers;
|
|
324
|
+
this.filled = new Uint8Array(layers);
|
|
325
|
+
this.views = [];
|
|
326
|
+
for (let layer = 0; layer < layers; layer += 1) {
|
|
327
|
+
const perLevel = [];
|
|
328
|
+
for (let level = 0; level <= this.level; level += 1) {
|
|
329
|
+
perLevel.push(this.targets.array.createView({
|
|
330
|
+
label: `probe.array ${String(layer)}.${String(level)}`,
|
|
331
|
+
dimension: '2d',
|
|
332
|
+
baseMipLevel: level,
|
|
333
|
+
mipLevelCount: 1,
|
|
334
|
+
baseArrayLayer: layer,
|
|
335
|
+
arrayLayerCount: 1,
|
|
336
|
+
}));
|
|
337
|
+
}
|
|
338
|
+
this.views.push(perLevel);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/** Whether every layer has had its chain written, which is what makes the array safe to sample. */
|
|
342
|
+
get complete() {
|
|
343
|
+
if (this.layers === 0)
|
|
344
|
+
return false;
|
|
345
|
+
for (let layer = 0; layer < this.layers; layer += 1) {
|
|
346
|
+
if (this.filled[layer] !== 1)
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Refresh this frame's share of the grid.
|
|
353
|
+
*
|
|
354
|
+
* Returns how many probes were baked, which is zero when there is nothing to trace against.
|
|
355
|
+
*/
|
|
356
|
+
bake(encoder, field, grid, seeded, sun) {
|
|
357
|
+
if (this.layers !== grid.layers)
|
|
358
|
+
this.setGrid(grid.layers);
|
|
359
|
+
const scheduled = probeUpdateSchedule(grid.layers, PROBES_PER_FRAME, this.frameIndex, this.scheduleScratch);
|
|
360
|
+
if (scheduled === 0)
|
|
361
|
+
return 0;
|
|
362
|
+
const queue = this.device.queue;
|
|
363
|
+
for (let slot = 0; slot < scheduled; slot += 1) {
|
|
364
|
+
this.scheduleUpload[slot] = this.scheduleScratch[slot];
|
|
365
|
+
}
|
|
366
|
+
queue.writeBuffer(this.scheduleBuffer, 0, this.scheduleUpload, 0, scheduled);
|
|
367
|
+
/* The march, from the same defaults `gi/traceField.ts` gives the reference. */
|
|
368
|
+
this.marchInts[0] = PROBE_MARCH_DEFAULTS.steps;
|
|
369
|
+
this.marchInts[1] = field.levels;
|
|
370
|
+
this.marchInts[2] = field.side;
|
|
371
|
+
this.marchInts[3] = scheduled * PROBE_DIRECTIONS;
|
|
372
|
+
this.marchScratch[4] = PROBE_MARCH_DEFAULTS.reachM;
|
|
373
|
+
this.marchScratch[5] = PROBE_MARCH_DEFAULTS.hitEpsilonM;
|
|
374
|
+
this.marchScratch[6] = field.finestStep;
|
|
375
|
+
this.marchScratch[7] = PROBE_MARCH_DEFAULTS.coneAngle;
|
|
376
|
+
this.marchScratch[8] = field.outerBounds[0];
|
|
377
|
+
this.marchScratch[9] = field.outerBounds[1];
|
|
378
|
+
this.marchScratch[10] = field.outerBounds[2];
|
|
379
|
+
this.marchScratch[12] = field.outerBounds[3];
|
|
380
|
+
this.marchScratch[13] = field.outerBounds[4];
|
|
381
|
+
this.marchScratch[14] = field.outerBounds[5];
|
|
382
|
+
queue.writeBuffer(this.marchBuffer, 0, this.marchScratch);
|
|
383
|
+
for (let axis = 0; axis < 3; axis += 1) {
|
|
384
|
+
this.bakeScratch[BAKE_ORIGIN + axis] = grid.origin[axis];
|
|
385
|
+
this.bakeScratch[BAKE_SPACING + axis] = grid.spacing[axis];
|
|
386
|
+
this.bakeScratch[BAKE_COUNTS + axis] = grid.counts[axis];
|
|
387
|
+
this.volumeScratch[VOLUME_ORIGIN + axis] = grid.origin[axis];
|
|
388
|
+
this.volumeScratch[VOLUME_INV_SPACING + axis] = grid.invSpacing[axis];
|
|
389
|
+
this.volumeScratch[VOLUME_COUNTS + axis] = grid.counts[axis];
|
|
390
|
+
}
|
|
391
|
+
this.bakeScratch[BAKE_EDGE] = this.levelEdge;
|
|
392
|
+
this.bakeScratch[BAKE_FRAME] = this.frameIndex;
|
|
393
|
+
this.bakeScratch[BAKE_SCHEDULED] = scheduled;
|
|
394
|
+
/*
|
|
395
|
+
* **The sun, because the trace shades what it hits rather than reading a capture.** That is
|
|
396
|
+
* the whole of what a traced grid buys over a rasterised one: a light that moves changes the
|
|
397
|
+
* bounce at the next refresh, where a bake keeps sending the light it was taken under.
|
|
398
|
+
*/
|
|
399
|
+
for (let axis = 0; axis < 3; axis += 1) {
|
|
400
|
+
this.bakeScratch[BAKE_SUN_DIR + axis] = sun.direction[axis] ?? 0;
|
|
401
|
+
this.bakeScratch[BAKE_SUN_COLOUR + axis] = sun.colour[axis] ?? 0;
|
|
402
|
+
this.bakeScratch[BAKE_SKY_COLOUR + axis] = sun.sky[axis] ?? 0;
|
|
403
|
+
}
|
|
404
|
+
queue.writeBuffer(this.bakeBuffer, 0, this.bakeScratch);
|
|
405
|
+
this.volumeScratch[VOLUME_EDGE] = this.levelEdge;
|
|
406
|
+
this.volumeScratch[VOLUME_LEVEL] = this.level;
|
|
407
|
+
/*
|
|
408
|
+
* **Level 0, which is radiance**, and it is what a ray gathers. The irradiance level above is
|
|
409
|
+
* what the bake *writes*; reading it back as though it were radiance is what made the first
|
|
410
|
+
* traced room dimmer and greyer than the rasterised one — see `probeVolumeRadianceAt`.
|
|
411
|
+
*/
|
|
412
|
+
this.volumeScratch[VOLUME_RADIANCE_EDGE] = this.targets.edge;
|
|
413
|
+
this.volumeScratch[VOLUME_RADIANCE_LEVEL] = 0;
|
|
414
|
+
queue.writeBuffer(this.volumeBuffer, 0, this.volumeScratch);
|
|
415
|
+
if (this.boundTo !== field || this.computeGroup === null) {
|
|
416
|
+
this.computeGroup = this.device.createBindGroup({
|
|
417
|
+
label: 'probe bake',
|
|
418
|
+
layout: this.computeLayout,
|
|
419
|
+
entries: [
|
|
420
|
+
{ binding: 0, resource: { buffer: field.cascades } },
|
|
421
|
+
{ binding: 1, resource: { buffer: field.samples } },
|
|
422
|
+
{ binding: 2, resource: { buffer: this.marchBuffer } },
|
|
423
|
+
{ binding: 3, resource: { buffer: this.bakeBuffer } },
|
|
424
|
+
{ binding: 4, resource: { buffer: this.scheduleBuffer } },
|
|
425
|
+
{ binding: 5, resource: { buffer: this.rayBuffer } },
|
|
426
|
+
{ binding: 6, resource: { buffer: this.irradianceBuffer } },
|
|
427
|
+
{ binding: 7, resource: { buffer: this.volumeBuffer } },
|
|
428
|
+
{ binding: 8, resource: this.targets.view },
|
|
429
|
+
{ binding: 9, resource: this.targets.sampler },
|
|
430
|
+
{ binding: 10, resource: { buffer: field.albedo } },
|
|
431
|
+
],
|
|
432
|
+
});
|
|
433
|
+
this.boundTo = field;
|
|
434
|
+
}
|
|
435
|
+
const pass = encoder.beginComputePass({
|
|
436
|
+
label: 'probe bake',
|
|
437
|
+
timestampWrites: this.queries === null
|
|
438
|
+
? undefined
|
|
439
|
+
: { querySet: this.queries, beginningOfPassWriteIndex: 0, endOfPassWriteIndex: 1 },
|
|
440
|
+
});
|
|
441
|
+
pass.setBindGroup(0, this.computeGroup);
|
|
442
|
+
pass.setPipeline(this.tracePipeline);
|
|
443
|
+
pass.dispatchWorkgroups(Math.ceil((scheduled * PROBE_DIRECTIONS) / PROBE_BAKE_WORKGROUP), 1, 1);
|
|
444
|
+
pass.setPipeline(this.convolvePipeline);
|
|
445
|
+
pass.dispatchWorkgroups(Math.ceil((scheduled * this.texels) / PROBE_BAKE_WORKGROUP), 1, 1);
|
|
446
|
+
pass.end();
|
|
447
|
+
if (this.queries !== null && this.queryResolve !== null && this.queryRead !== null) {
|
|
448
|
+
if (!this.queryCopied && !this.queryMapping) {
|
|
449
|
+
encoder.resolveQuerySet(this.queries, 0, 2, this.queryResolve, 0);
|
|
450
|
+
encoder.copyBufferToBuffer(this.queryResolve, 0, this.queryRead, 0, 16);
|
|
451
|
+
this.queryCopied = true;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
for (let slot = 0; slot < scheduled; slot += 1) {
|
|
455
|
+
const layer = this.scheduleScratch[slot];
|
|
456
|
+
const first = this.filled[layer] !== 1 && !seeded;
|
|
457
|
+
/* Every level once for an unseeded layer, then the irradiance level for ever. See above. */
|
|
458
|
+
const from = first ? 0 : this.level;
|
|
459
|
+
for (let level = from; level <= this.level; level += 1) {
|
|
460
|
+
const view = this.views[layer]?.[level];
|
|
461
|
+
if (view === undefined)
|
|
462
|
+
continue;
|
|
463
|
+
const target = encoder.beginRenderPass({
|
|
464
|
+
label: `probe blit ${String(layer)}.${String(level)}`,
|
|
465
|
+
colorAttachments: [{ view, loadOp: 'clear', storeOp: 'store', clearValue: BLACK }],
|
|
466
|
+
});
|
|
467
|
+
target.setPipeline(this.blitPipeline);
|
|
468
|
+
target.setBindGroup(0, this.blitGroup, [this.blitOffset(slot, level)]);
|
|
469
|
+
target.draw(3, 1, 0, 0);
|
|
470
|
+
target.end();
|
|
471
|
+
}
|
|
472
|
+
this.filled[layer] = 1;
|
|
473
|
+
}
|
|
474
|
+
this.frameIndex += 1;
|
|
475
|
+
return scheduled;
|
|
476
|
+
}
|
|
477
|
+
dispose() {
|
|
478
|
+
this.queries?.destroy();
|
|
479
|
+
this.queryResolve?.destroy();
|
|
480
|
+
this.queryRead?.destroy();
|
|
481
|
+
this.marchBuffer.destroy();
|
|
482
|
+
this.bakeBuffer.destroy();
|
|
483
|
+
this.volumeBuffer.destroy();
|
|
484
|
+
this.scheduleBuffer.destroy();
|
|
485
|
+
this.rayBuffer.destroy();
|
|
486
|
+
this.irradianceBuffer.destroy();
|
|
487
|
+
this.blitParams.destroy();
|
|
488
|
+
this.views = [];
|
|
489
|
+
this.computeGroup = null;
|
|
490
|
+
this.boundTo = null;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
const BLACK = { r: 0, g: 0, b: 0, a: 1 };
|