@driftengine/core 3.62.0 → 4.0.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 +70 -4
- package/dist/index.js +123 -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 +47 -14
- package/dist/render/backend/webgpu/surfaceTexturePass.js +128 -80
- 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 +261 -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 +158 -88
- 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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FrameBudget } from '../budget.js';
|
|
2
|
+
import { MaterialChanges, ownsMaterial } from '../materialChanges.js';
|
|
2
3
|
import { mat4 } from 'gl-matrix';
|
|
3
4
|
import { DEPTH_CLEAR, DEPTH_OFFSET_SIGN, GL_DEPTH_REMAP, MAX_DEPTH_LAYER, depthOffsetForLayer, GL_SHADOW_REMAP, REVERSED_DEPTH, SHADOW_DEPTH_CLEAR, glDepthFuncEqual, glShadowDepthFunc, } from '../../depthConvention.js';
|
|
4
5
|
import { PickableSet } from '../../pickable.js';
|
|
@@ -11,6 +12,7 @@ import { REFLECTION_EDGE_FADE, ReflectionQueue } from '../../screenSpaceReflecti
|
|
|
11
12
|
import { DecalQueue } from '../../decalQueue.js';
|
|
12
13
|
import { OitPass } from '../../oitPass.js';
|
|
13
14
|
import { OIT_MULTISAMPLE_REFUSAL } from '../../orderIndependent.js';
|
|
15
|
+
import { INDIRECT_LIGHT_WEBGL2_REFUSAL } from '../../gi/probeTrace.js';
|
|
14
16
|
import { TranslucentQueue } from '../../translucentQueue.js';
|
|
15
17
|
import { createFrustum, frustumFromViewProjection } from '../../../math/frustum.js';
|
|
16
18
|
import { OcclusionBuffer } from '../../occlusion.js';
|
|
@@ -34,7 +36,7 @@ import { SkinPaletteTexture } from './skinPaletteTexture.js';
|
|
|
34
36
|
/* The codes the shader reads, stated once in `vertexDefaults.ts` for both backends. */
|
|
35
37
|
import { LIGHT_VOLUME_VERT, lightVolumeFrag } from '../../shaders/lightVolume.js';
|
|
36
38
|
import { PANEL_FRAG, PANEL_VERT } from '../../shaders/panel.js';
|
|
37
|
-
import { ReflectionProbe } from '../../reflectionProbe.js';
|
|
39
|
+
import { ReflectionProbe, cubeFaceProjection } from '../../reflectionProbe.js';
|
|
38
40
|
import { EnvProbeArray } from '../../envProbeArray.js';
|
|
39
41
|
import { ProbeGrid, SINGLE_PROBE, UNIT_STEP, WORLD_ORIGIN, sameGrid } from '../../probeGrid.js';
|
|
40
42
|
import { octahedralEdgeFor } from '../../prefilterEnvMap.js';
|
|
@@ -749,6 +751,13 @@ export class WebGL2Renderer {
|
|
|
749
751
|
reversedDepth = false;
|
|
750
752
|
/** `GL_DEPTH_REMAP * camera.viewProjection`, rebuilt once a frame. */
|
|
751
753
|
sceneViewProj = new Float32Array(16);
|
|
754
|
+
/**
|
|
755
|
+
* The same matrix with clip y negated, for the six faces of a probe.
|
|
756
|
+
*
|
|
757
|
+
* Its own buffer rather than `sceneViewProj`, because `cubeFaceProjection` reads what
|
|
758
|
+
* `sceneMatrix` just wrote and the two would be the same array.
|
|
759
|
+
*/
|
|
760
|
+
cubeFaceViewProj = new Float32Array(16);
|
|
752
761
|
/**
|
|
753
762
|
* One buffer per shadow matrix that outlives a call, and that is not fussiness.
|
|
754
763
|
*
|
|
@@ -776,7 +785,9 @@ export class WebGL2Renderer {
|
|
|
776
785
|
* the camera's matrix unchanged and multiplies nothing.
|
|
777
786
|
*/
|
|
778
787
|
viewProjFor(camera) {
|
|
779
|
-
const scene = this.
|
|
788
|
+
const scene = this.probePassActive
|
|
789
|
+
? cubeFaceProjection(this.cubeFaceViewProj, this.sceneMatrix(camera.viewProjection))
|
|
790
|
+
: this.sceneMatrix(camera.viewProjection);
|
|
780
791
|
/*
|
|
781
792
|
* **The jitter goes on here and nowhere else.** This is the one funnel every geometry upload
|
|
782
793
|
* passes through, so one line covers the mesh passes, the sky, the water and the effects
|
|
@@ -865,6 +876,7 @@ export class WebGL2Renderer {
|
|
|
865
876
|
*/
|
|
866
877
|
casterSink = {
|
|
867
878
|
mesh: (mesh, model) => {
|
|
879
|
+
this.shadowDrawBudget.ask();
|
|
868
880
|
const { gl } = this;
|
|
869
881
|
gl.uniformMatrix4fv(this.depthUniforms['uModel'] ?? null, false, model);
|
|
870
882
|
/*
|
|
@@ -886,6 +898,7 @@ export class WebGL2Renderer {
|
|
|
886
898
|
const count = Math.min(data.count, gpuBatch.capacity);
|
|
887
899
|
if (count === 0)
|
|
888
900
|
return;
|
|
901
|
+
this.shadowDrawBudget.ask();
|
|
889
902
|
const u = this.depthInstancedUniforms;
|
|
890
903
|
gl.useProgram(this.depthInstancedProgram);
|
|
891
904
|
gl.uniformMatrix4fv(u['uLightViewProj'] ?? null, false, this.activeDepthViewProj);
|
|
@@ -896,6 +909,7 @@ export class WebGL2Renderer {
|
|
|
896
909
|
gl.useProgram(this.depthProgram);
|
|
897
910
|
},
|
|
898
911
|
skinnedMesh: (mesh, model, palette) => {
|
|
912
|
+
this.shadowDrawBudget.ask();
|
|
899
913
|
const { gl } = this;
|
|
900
914
|
const u = this.depthSkinnedUniforms;
|
|
901
915
|
gl.useProgram(this.depthSkinnedProgram);
|
|
@@ -920,6 +934,7 @@ export class WebGL2Renderer {
|
|
|
920
934
|
scatter: (scatter, data, windX, windZ, windGust, timeSeconds, trample = null) => {
|
|
921
935
|
if (data.count === 0)
|
|
922
936
|
return;
|
|
937
|
+
this.scatterDepthBudget.ask();
|
|
923
938
|
const { gl } = this;
|
|
924
939
|
const u = this.scatterDepthUniforms;
|
|
925
940
|
gl.useProgram(this.scatterDepthProgram);
|
|
@@ -1035,6 +1050,39 @@ export class WebGL2Renderer {
|
|
|
1035
1050
|
addOccluder(min, max, model) {
|
|
1036
1051
|
this.occlusion?.addOccluder(min, max, model);
|
|
1037
1052
|
}
|
|
1053
|
+
/**
|
|
1054
|
+
* Declare a baked distance field that indirect light may be traced against.
|
|
1055
|
+
*
|
|
1056
|
+
* **Recorded by nothing on this backend, and that is the refusal rather than an oversight.**
|
|
1057
|
+
* Composing the world's field and marching probes through it is compute, and WebGL2 has no
|
|
1058
|
+
* compute stage — `INDIRECT_LIGHT_WEBGL2_REFUSAL` says so once a frame-loop when
|
|
1059
|
+
* `quality.indirectLight` is on. The method exists here because `RendererApi` is this class's
|
|
1060
|
+
* shape, and a consumer that declares its fields unconditionally must not have to ask which
|
|
1061
|
+
* backend it got: this is a no-op for the same reason `addOccluder` is one when the profile
|
|
1062
|
+
* asked for no occlusion buffer.
|
|
1063
|
+
*
|
|
1064
|
+
* The field is in the model matrix's own space and the matrix must carry uniform scale only.
|
|
1065
|
+
* `composeGlobalField` gives the reason: a distance is not preserved by a non-uniform scale.
|
|
1066
|
+
*/
|
|
1067
|
+
addDistanceField(_field, _model, _albedo) {
|
|
1068
|
+
/* Deliberately nothing. See the comment above. */
|
|
1069
|
+
}
|
|
1070
|
+
/** Forget the fields declared this frame. A no-op here, as `addDistanceField` is. */
|
|
1071
|
+
clearDistanceFields() {
|
|
1072
|
+
/* Deliberately nothing. See `addDistanceField`. */
|
|
1073
|
+
}
|
|
1074
|
+
/** Never measured here, because nothing is composed. See `addDistanceField`. */
|
|
1075
|
+
get distanceFieldMs() {
|
|
1076
|
+
return null;
|
|
1077
|
+
}
|
|
1078
|
+
/** Never traced here either, so there is no refresh to time. See `addDistanceField`. */
|
|
1079
|
+
get indirectBakeMs() {
|
|
1080
|
+
return null;
|
|
1081
|
+
}
|
|
1082
|
+
/** Nothing to read, for the same reason. A consumer may call it unconditionally. */
|
|
1083
|
+
readDistanceFieldTimings() {
|
|
1084
|
+
/* Deliberately nothing. See `addDistanceField`. */
|
|
1085
|
+
}
|
|
1038
1086
|
/**
|
|
1039
1087
|
* Whether a mesh is entirely behind the occluders declared this frame.
|
|
1040
1088
|
*
|
|
@@ -1066,7 +1114,14 @@ export class WebGL2Renderer {
|
|
|
1066
1114
|
registerPass(definition) {
|
|
1067
1115
|
const handle = registerIn(this.passes, definition);
|
|
1068
1116
|
/* Identity: this backend's clip space is the one the projections are built for. */
|
|
1069
|
-
|
|
1117
|
+
/* Both are identity here: this backend runs the GLSL natively, so there is nothing to
|
|
1118
|
+
correct and nothing a generator has flipped. */
|
|
1119
|
+
this.passDevice ??= {
|
|
1120
|
+
backend: 'webgl2',
|
|
1121
|
+
gl: this.gl,
|
|
1122
|
+
clipCorrection: IDENTITY_CLIP,
|
|
1123
|
+
depthCorrection: IDENTITY_CLIP,
|
|
1124
|
+
};
|
|
1070
1125
|
if (definition.prepare !== undefined)
|
|
1071
1126
|
this.preparingPasses++;
|
|
1072
1127
|
definition.init?.(this.passDevice);
|
|
@@ -2093,6 +2148,7 @@ export class WebGL2Renderer {
|
|
|
2093
2148
|
setMaterial(material) {
|
|
2094
2149
|
if (this.contextLost)
|
|
2095
2150
|
return;
|
|
2151
|
+
this.materials.dirty();
|
|
2096
2152
|
this.currentSurfaceTexture = material?.albedo ?? null;
|
|
2097
2153
|
/*
|
|
2098
2154
|
* Written to every flat program, because material state persists across draws and a skinned
|
|
@@ -2244,6 +2300,7 @@ export class WebGL2Renderer {
|
|
|
2244
2300
|
setSurfaceReflectivity(amount) {
|
|
2245
2301
|
if (this.contextLost)
|
|
2246
2302
|
return;
|
|
2303
|
+
this.materials.dirty();
|
|
2247
2304
|
this.useFlatProgram();
|
|
2248
2305
|
this.gl.uniform1f(this.flatUniforms['uReflectivity'] ?? null, Math.min(1, Math.max(0, amount)));
|
|
2249
2306
|
}
|
|
@@ -2262,6 +2319,7 @@ export class WebGL2Renderer {
|
|
|
2262
2319
|
setEnvironmentGain(gain) {
|
|
2263
2320
|
if (this.contextLost)
|
|
2264
2321
|
return;
|
|
2322
|
+
this.materials.dirty();
|
|
2265
2323
|
this.useFlatProgram();
|
|
2266
2324
|
this.gl.uniform1f(this.flatUniforms['uEnvironmentGain'] ?? null, Math.max(0, gain));
|
|
2267
2325
|
}
|
|
@@ -2289,6 +2347,7 @@ export class WebGL2Renderer {
|
|
|
2289
2347
|
setSurfaceGrain(amount) {
|
|
2290
2348
|
if (this.contextLost)
|
|
2291
2349
|
return;
|
|
2350
|
+
this.materials.dirty();
|
|
2292
2351
|
this.useFlatProgram();
|
|
2293
2352
|
this.gl.uniform1f(this.flatUniforms['uGrain'] ?? null, Math.min(1, Math.max(0, amount)));
|
|
2294
2353
|
}
|
|
@@ -2318,6 +2377,7 @@ export class WebGL2Renderer {
|
|
|
2318
2377
|
setSurfaceRelief(amount, cyclesPerMetre = 60) {
|
|
2319
2378
|
if (this.contextLost)
|
|
2320
2379
|
return;
|
|
2380
|
+
this.materials.dirty();
|
|
2321
2381
|
this.useFlatProgram();
|
|
2322
2382
|
const u = this.flatUniforms;
|
|
2323
2383
|
this.gl.uniform1f(u['uRelief'] ?? null, Math.min(1, Math.max(0, amount)));
|
|
@@ -2351,6 +2411,7 @@ export class WebGL2Renderer {
|
|
|
2351
2411
|
setSurfaceTextureRelief(scale) {
|
|
2352
2412
|
if (this.contextLost)
|
|
2353
2413
|
return;
|
|
2414
|
+
this.materials.dirty();
|
|
2354
2415
|
this.useFlatProgram();
|
|
2355
2416
|
this.gl.uniform1f(this.flatUniforms['uTextureRelief'] ?? null, Number.isFinite(scale) ? scale : 0);
|
|
2356
2417
|
}
|
|
@@ -2378,6 +2439,7 @@ export class WebGL2Renderer {
|
|
|
2378
2439
|
setEmissiveGain(gain) {
|
|
2379
2440
|
if (this.contextLost)
|
|
2380
2441
|
return;
|
|
2442
|
+
this.materials.dirty();
|
|
2381
2443
|
this.useFlatProgram();
|
|
2382
2444
|
this.gl.uniform1f(this.flatUniforms['uEmissiveGain'] ?? null, gain);
|
|
2383
2445
|
}
|
|
@@ -2482,6 +2544,11 @@ export class WebGL2Renderer {
|
|
|
2482
2544
|
const lit = options.lit ?? true;
|
|
2483
2545
|
const fog = options.fog ?? true;
|
|
2484
2546
|
const toneMapped = options.toneMapped ?? true;
|
|
2547
|
+
/* An instanced draw does not refract. See `materialChanges.ts`. */
|
|
2548
|
+
const own = ownsMaterial({ opacity, lit, fog, toneMapped, refracting: false });
|
|
2549
|
+
if (own)
|
|
2550
|
+
this.materials.dirty();
|
|
2551
|
+
this.takeMaterial();
|
|
2485
2552
|
const depthWrite = options.depthWrite ?? true;
|
|
2486
2553
|
const layer = Math.min(Math.max(Math.round(options.depthLayer ?? 0), 0), MAX_DEPTH_LAYER);
|
|
2487
2554
|
if (opacity < 1)
|
|
@@ -2559,6 +2626,8 @@ export class WebGL2Renderer {
|
|
|
2559
2626
|
gl.uniform1i(u['uFogEnabled'] ?? null, 1);
|
|
2560
2627
|
if (!toneMapped)
|
|
2561
2628
|
gl.uniform1i(u['uOutputTransform'] ?? null, this.gradeCode());
|
|
2629
|
+
if (own)
|
|
2630
|
+
this.materials.dirty();
|
|
2562
2631
|
this.useFlatProgram();
|
|
2563
2632
|
}
|
|
2564
2633
|
disposeMesh(mesh) {
|
|
@@ -2657,7 +2726,9 @@ export class WebGL2Renderer {
|
|
|
2657
2726
|
// raining dust into the sea.
|
|
2658
2727
|
const surface = env.underwater?.surfaceY;
|
|
2659
2728
|
const submerged = surface !== undefined && (camera.position[1] ?? 0) < surface;
|
|
2660
|
-
streaks.draw(this.gl, this.frameViewFor(camera), wind, timeSeconds, tint, submerged)
|
|
2729
|
+
if (streaks.draw(this.gl, this.frameViewFor(camera), wind, timeSeconds, tint, submerged)) {
|
|
2730
|
+
this.windStreakBudget.ask();
|
|
2731
|
+
}
|
|
2661
2732
|
}
|
|
2662
2733
|
/**
|
|
2663
2734
|
* A 3D text object: one string, drawn as instanced glyph cubes over the
|
|
@@ -2682,7 +2753,9 @@ export class WebGL2Renderer {
|
|
|
2682
2753
|
* whatever box the caller lays out in, and the game's own card is not always the canvas.
|
|
2683
2754
|
*/
|
|
2684
2755
|
drawText(text, viewportWidth, viewportHeight, originX, originY, style, timeSec) {
|
|
2685
|
-
text.draw(viewportWidth, viewportHeight, originX, originY, style, timeSec)
|
|
2756
|
+
if (text.draw(viewportWidth, viewportHeight, originX, originY, style, timeSec)) {
|
|
2757
|
+
this.textBudget.ask();
|
|
2758
|
+
}
|
|
2686
2759
|
}
|
|
2687
2760
|
/** Width of the string this handle currently holds, in pixels at a given cell size. */
|
|
2688
2761
|
textWidth(text, cellSize) {
|
|
@@ -2757,6 +2830,7 @@ export class WebGL2Renderer {
|
|
|
2757
2830
|
return;
|
|
2758
2831
|
/* Geometry, so the remapped matrix: `frameViewProj` itself stays raw for the motion blur. */
|
|
2759
2832
|
if (handle.draw(this.sceneMatrix(viewProj), model, color, opacity, this.gradeCode(), this.gradeExposure())) {
|
|
2833
|
+
this.sdfTextBudget.ask();
|
|
2760
2834
|
this.restoreSurfaceTextureUnit();
|
|
2761
2835
|
}
|
|
2762
2836
|
}
|
|
@@ -2768,6 +2842,7 @@ export class WebGL2Renderer {
|
|
|
2768
2842
|
return new FlockRenderer(this.gl, count);
|
|
2769
2843
|
}
|
|
2770
2844
|
drawFlock(flock, camera, timeSeconds, params, tint, windX = 0, windZ = 0) {
|
|
2845
|
+
this.flockBudget.ask();
|
|
2771
2846
|
flock.draw(this.gl, this.frameViewFor(camera), timeSeconds, params, tint, windX, windZ);
|
|
2772
2847
|
}
|
|
2773
2848
|
/**
|
|
@@ -2864,8 +2939,11 @@ export class WebGL2Renderer {
|
|
|
2864
2939
|
return;
|
|
2865
2940
|
const { gl } = this;
|
|
2866
2941
|
const u = batch.uniforms;
|
|
2867
|
-
gl.useProgram(batch.program);
|
|
2868
2942
|
const count = batch.upload(gl, data);
|
|
2943
|
+
if (count === 0)
|
|
2944
|
+
return;
|
|
2945
|
+
this.boltBudget.ask();
|
|
2946
|
+
gl.useProgram(batch.program);
|
|
2869
2947
|
gl.uniformMatrix4fv(u['uViewProj'] ?? null, false, this.viewProjFor(camera));
|
|
2870
2948
|
gl.uniform3fv(u['uCameraPos'] ?? null, camera.position);
|
|
2871
2949
|
gl.uniform1f(u['uTime'] ?? null, timeSeconds);
|
|
@@ -2917,8 +2995,11 @@ export class WebGL2Renderer {
|
|
|
2917
2995
|
return;
|
|
2918
2996
|
const { gl } = this;
|
|
2919
2997
|
const u = lines.uniforms;
|
|
2920
|
-
gl.useProgram(lines.program);
|
|
2921
2998
|
const count = lines.upload(gl, data);
|
|
2999
|
+
if (count === 0)
|
|
3000
|
+
return;
|
|
3001
|
+
this.lineBudget.ask();
|
|
3002
|
+
gl.useProgram(lines.program);
|
|
2922
3003
|
gl.uniformMatrix4fv(u['uViewProj'] ?? null, false, this.viewProjFor(camera));
|
|
2923
3004
|
gl.uniformMatrix4fv(u['uModel'] ?? null, false, model);
|
|
2924
3005
|
gl.uniform3fv(u['uCameraPos'] ?? null, camera.position);
|
|
@@ -3093,6 +3174,7 @@ export class WebGL2Renderer {
|
|
|
3093
3174
|
drawWater(water, camera, timeSeconds, settings, env, windX = 0, windZ = 0) {
|
|
3094
3175
|
if (!this.quality.water)
|
|
3095
3176
|
return;
|
|
3177
|
+
this.waterBudget.ask();
|
|
3096
3178
|
water.draw(this.gl, this.frameViewFor(camera), timeSeconds, settings, env.directionalDir, env.directionalColor, env.ambient, env, this.quality.underwaterAtmosphere, this.reflectionReadyThisFrame ? this.planarReflection : null, env, this.quality.pointLightFalloff, windX, windZ);
|
|
3097
3179
|
}
|
|
3098
3180
|
/**
|
|
@@ -3102,7 +3184,9 @@ export class WebGL2Renderer {
|
|
|
3102
3184
|
drawCaustics(caustics, camera, timeSeconds, env, windX = 0, windZ = 0, strength = 1) {
|
|
3103
3185
|
if (caustics === null || !this.quality.water)
|
|
3104
3186
|
return;
|
|
3105
|
-
caustics.draw(this.gl, this.frameViewFor(camera), timeSeconds, env.directionalDir, env.directionalColor, env.ambient, env, this.quality.underwaterAtmosphere, windX, windZ, strength);
|
|
3187
|
+
const drew = caustics.draw(this.gl, this.frameViewFor(camera), timeSeconds, env.directionalDir, env.directionalColor, env.ambient, env, this.quality.underwaterAtmosphere, windX, windZ, strength);
|
|
3188
|
+
if (drew)
|
|
3189
|
+
this.causticsBudget.ask();
|
|
3106
3190
|
}
|
|
3107
3191
|
/**
|
|
3108
3192
|
* Begin a scene render mirrored across a horizontal plane. Draw ordinary
|
|
@@ -3160,6 +3244,21 @@ export class WebGL2Renderer {
|
|
|
3160
3244
|
get aspect() {
|
|
3161
3245
|
return this.canvas.width / Math.max(this.canvas.height, 1);
|
|
3162
3246
|
}
|
|
3247
|
+
/**
|
|
3248
|
+
* The size the world is drawn at, which on this backend is always the drawing buffer.
|
|
3249
|
+
*
|
|
3250
|
+
* **Here so that a contributed pass has one question to ask on both backends.** WebGPU can draw
|
|
3251
|
+
* the world smaller than the canvas and let its composite enlarge it — `quality.reconstruction`
|
|
3252
|
+
* — and a pass filling a target of its own has to follow that size or draw a picture the frame
|
|
3253
|
+
* pass clips. This backend has no compute stage and no reconstruction, so the answer never moves;
|
|
3254
|
+
* a pass that reads it is correct on both, and one that reads `canvas.width` is correct on one.
|
|
3255
|
+
*/
|
|
3256
|
+
get sceneWidth() {
|
|
3257
|
+
return Math.max(1, this.canvas.width);
|
|
3258
|
+
}
|
|
3259
|
+
get sceneHeight() {
|
|
3260
|
+
return Math.max(1, this.canvas.height);
|
|
3261
|
+
}
|
|
3163
3262
|
/**
|
|
3164
3263
|
* Point rendering back at the frame's own target, whole.
|
|
3165
3264
|
*
|
|
@@ -4001,6 +4100,9 @@ export class WebGL2Renderer {
|
|
|
4001
4100
|
fillPanel(rect, color, alpha) {
|
|
4002
4101
|
if (alpha <= 0 || rect.width <= 0 || rect.height <= 0)
|
|
4003
4102
|
return;
|
|
4103
|
+
/* Counted against no ceiling: the other backend refuses past its own, and a consumer here
|
|
4104
|
+
should be able to see that coming. See `budget.ts`. */
|
|
4105
|
+
this.panelBudget.ask();
|
|
4004
4106
|
const { gl } = this;
|
|
4005
4107
|
gl.useProgram(this.panelProgram);
|
|
4006
4108
|
gl.bindVertexArray(this.panelVao);
|
|
@@ -4271,6 +4373,25 @@ export class WebGL2Renderer {
|
|
|
4271
4373
|
*/
|
|
4272
4374
|
budget = new FrameBudget();
|
|
4273
4375
|
drawBudget = this.budget.line('draws', null);
|
|
4376
|
+
/**
|
|
4377
|
+
* Every line the other backend declares, in its order and with none of its ceilings.
|
|
4378
|
+
*
|
|
4379
|
+
* **Counted after the same guards**, so one scene reports one number on both: the verbs each
|
|
4380
|
+
* ask once they are past the checks that make them draw nothing on either backend — a panel
|
|
4381
|
+
* with no alpha, a string with no glyphs, a beam with no strength, a calm wind — and a material
|
|
4382
|
+
* change is counted by the rule both share (`materialChanges.ts`). `webgpu/renderer.test.ts`
|
|
4383
|
+
* runs one scene through both and compares every line.
|
|
4384
|
+
*/
|
|
4385
|
+
materialBudget = this.budget.line('materials', null);
|
|
4386
|
+
/** Whether the next mesh draw shares the open material or opens one, by the rule both count. */
|
|
4387
|
+
materials = new MaterialChanges();
|
|
4388
|
+
/** A mesh draw: counted as a material change when something has changed the material since. */
|
|
4389
|
+
takeMaterial() {
|
|
4390
|
+
if (this.materials.open)
|
|
4391
|
+
return;
|
|
4392
|
+
this.materialBudget.ask();
|
|
4393
|
+
this.materials.slot = 0;
|
|
4394
|
+
}
|
|
4274
4395
|
/**
|
|
4275
4396
|
* Declared here and never asked, because this backend builds none.
|
|
4276
4397
|
*
|
|
@@ -4282,6 +4403,19 @@ export class WebGL2Renderer {
|
|
|
4282
4403
|
* being compared against should also be zero once the other backend's cache is warm.
|
|
4283
4404
|
*/
|
|
4284
4405
|
bindGroupBudget = this.budget.line('bind groups', null);
|
|
4406
|
+
shadowDrawBudget = this.budget.line('shadow draws', null);
|
|
4407
|
+
scatterDepthBudget = this.budget.line('scatter shadow draws', null);
|
|
4408
|
+
waterBudget = this.budget.line('water bodies', null);
|
|
4409
|
+
lightVolumeBudget = this.budget.line('light volumes', null);
|
|
4410
|
+
windStreakBudget = this.budget.line('wind streak fields', null);
|
|
4411
|
+
flockBudget = this.budget.line('flocks', null);
|
|
4412
|
+
boltBudget = this.budget.line('bolt batches', null);
|
|
4413
|
+
causticsBudget = this.budget.line('caustics', null);
|
|
4414
|
+
textBudget = this.budget.line('text draws', null);
|
|
4415
|
+
sdfTextBudget = this.budget.line('sdf text draws', null);
|
|
4416
|
+
lineBudget = this.budget.line('line draws', null);
|
|
4417
|
+
/** The other backend's panel ceiling, reported here as a count with none. */
|
|
4418
|
+
panelBudget = this.budget.line('panels', null);
|
|
4285
4419
|
/** What the frame just drawn asked for. See `budget.ts`, and the note on `budget` above. */
|
|
4286
4420
|
get frameBudget() {
|
|
4287
4421
|
return this.budget;
|
|
@@ -4372,6 +4506,8 @@ export class WebGL2Renderer {
|
|
|
4372
4506
|
* from one `RenderQuality` — see `OIT_MULTISAMPLE_REFUSAL` for why it is a constant and not two
|
|
4373
4507
|
* literals kept in step by hand.
|
|
4374
4508
|
*/
|
|
4509
|
+
/** Said once rather than every frame, as the translucent set's own refusal is. */
|
|
4510
|
+
indirectLightRefused = false;
|
|
4375
4511
|
refuseOitMultisampled() {
|
|
4376
4512
|
if (this.oitMultisampleRefused)
|
|
4377
4513
|
return;
|
|
@@ -4382,6 +4518,15 @@ export class WebGL2Renderer {
|
|
|
4382
4518
|
if (this.contextLost)
|
|
4383
4519
|
return;
|
|
4384
4520
|
this.budget.reset();
|
|
4521
|
+
this.materials.dirty();
|
|
4522
|
+
/*
|
|
4523
|
+
* Said once, for the reason `refuseOitMultisampled` gives: a quality setting that is enabled
|
|
4524
|
+
* and does nothing is the fault the capability clamp exists to prevent.
|
|
4525
|
+
*/
|
|
4526
|
+
if (this.quality.indirectLight && !this.indirectLightRefused) {
|
|
4527
|
+
this.indirectLightRefused = true;
|
|
4528
|
+
console.warn(INDIRECT_LIGHT_WEBGL2_REFUSAL);
|
|
4529
|
+
}
|
|
4385
4530
|
const { gl } = this;
|
|
4386
4531
|
this.reflectionReadyThisFrame = false;
|
|
4387
4532
|
/*
|
|
@@ -4624,6 +4769,16 @@ export class WebGL2Renderer {
|
|
|
4624
4769
|
this.translucentQueue.length > 0) {
|
|
4625
4770
|
const flat = this.flatUniforms;
|
|
4626
4771
|
const options = this.oitReplayOptions;
|
|
4772
|
+
/*
|
|
4773
|
+
* **The copy a refracting pane reads is taken here, before the buffers are bound.** Taking
|
|
4774
|
+
* it puts the scene's framebuffer back as the one drawn into, so taken inside the replay —
|
|
4775
|
+
* at the first pane that refracts, which is where it was taken until 2026-09-19 — it sent
|
|
4776
|
+
* that pane into the scene instead of the accumulation, and every refracting pane came out
|
|
4777
|
+
* flat paint with the effect on. The opaque frame is finished here, which is what a pane
|
|
4778
|
+
* should show; the latch then serves every pane in the replay. Only when something refracts.
|
|
4779
|
+
*/
|
|
4780
|
+
if (this.translucentQueue.refracts)
|
|
4781
|
+
this.sceneTarget?.snapshotColor();
|
|
4627
4782
|
this.oit.accumulateOit(this.canvas.width, this.canvas.height, oitDepth, (weighted) => {
|
|
4628
4783
|
this.oitReplaying = true;
|
|
4629
4784
|
this.useFlatProgram();
|
|
@@ -4795,6 +4950,8 @@ export class WebGL2Renderer {
|
|
|
4795
4950
|
}
|
|
4796
4951
|
/** Bind the flat pass once per frame; then issue any number of drawMesh calls. */
|
|
4797
4952
|
bindMeshPass(camera, env) {
|
|
4953
|
+
/* The pass's own material is reopened, so the next draw opens one. See `materialChanges.ts`. */
|
|
4954
|
+
this.materials.dirty();
|
|
4798
4955
|
/*
|
|
4799
4956
|
* Captured here rather than taken as an argument to `endFrame`, because this is the
|
|
4800
4957
|
* camera the world was drawn with and a caller should not have to hand it over twice.
|
|
@@ -5121,6 +5278,8 @@ export class WebGL2Renderer {
|
|
|
5121
5278
|
* are two numbers now.
|
|
5122
5279
|
*/
|
|
5123
5280
|
gl.uniform1f(u['uEnvironmentEdge'] ?? null, array?.edge ?? 1);
|
|
5281
|
+
/* Never on this backend: what fills a visibility map is a compute dispatch. See `probeGrid.ts`. */
|
|
5282
|
+
gl.uniform1f(u['uProbeVisibilityEnabled'] ?? null, 0);
|
|
5124
5283
|
gl.uniform1f(u['uEnvironmentIrradianceLevel'] ?? null, array?.irradianceLevel ?? 0);
|
|
5125
5284
|
/*
|
|
5126
5285
|
* Where the probes stand: four uniforms whatever the probe count, because this shader is
|
|
@@ -5249,7 +5408,15 @@ export class WebGL2Renderer {
|
|
|
5249
5408
|
* rebuilding vertex data every frame. Reset to white after the call, so a caller that
|
|
5250
5409
|
* passes one cannot leak it into the next draw.
|
|
5251
5410
|
*/
|
|
5252
|
-
tint = null
|
|
5411
|
+
tint = null,
|
|
5412
|
+
/**
|
|
5413
|
+
* Where the mesh was last frame, which this backend takes and ignores.
|
|
5414
|
+
*
|
|
5415
|
+
* Accepted rather than absent so that one scene draws through both renderers unchanged — the
|
|
5416
|
+
* parity rule this repository is built on. Reconstruction is WebGPU's, having no compute stage
|
|
5417
|
+
* here, so there is no motion target for this to be written into.
|
|
5418
|
+
*/
|
|
5419
|
+
_previousModel = null) {
|
|
5253
5420
|
if (this.contextLost)
|
|
5254
5421
|
return;
|
|
5255
5422
|
/* Geometry that has not all arrived is not drawn. See `Mesh.complete`. */
|
|
@@ -5276,6 +5443,7 @@ export class WebGL2Renderer {
|
|
|
5276
5443
|
if (this.quality.cullDraws && this.occluded(mesh.bounds, model))
|
|
5277
5444
|
return;
|
|
5278
5445
|
this.drawBudget.ask();
|
|
5446
|
+
this.takeMaterial();
|
|
5279
5447
|
const { gl } = this;
|
|
5280
5448
|
/*
|
|
5281
5449
|
* A rigged mesh takes the skinned program, an unrigged one the plain program.
|
|
@@ -5439,7 +5607,6 @@ export class WebGL2Renderer {
|
|
|
5439
5607
|
return;
|
|
5440
5608
|
if (opacity <= 0)
|
|
5441
5609
|
return;
|
|
5442
|
-
this.drawBudget.ask();
|
|
5443
5610
|
/*
|
|
5444
5611
|
* **Recorded rather than drawn**, when the effect is on and this is not already the replay.
|
|
5445
5612
|
* The two buffers are two blend states over the same geometry, so the set has to survive until
|
|
@@ -5449,6 +5616,9 @@ export class WebGL2Renderer {
|
|
|
5449
5616
|
this.translucentQueue.record(mesh, model, opacity, options);
|
|
5450
5617
|
return;
|
|
5451
5618
|
}
|
|
5619
|
+
/* Counted where it is submitted, as the other backend counts it: once per replay pass under
|
|
5620
|
+
order-independent transparency, and not once more when it was recorded. */
|
|
5621
|
+
this.drawBudget.ask();
|
|
5452
5622
|
const { gl } = this;
|
|
5453
5623
|
const u = this.flatUniforms;
|
|
5454
5624
|
this.useFlatProgram();
|
|
@@ -5509,6 +5679,12 @@ export class WebGL2Renderer {
|
|
|
5509
5679
|
* or a multiplicative blend for the whole set and turned depth writes off for all of it. A
|
|
5510
5680
|
* replayed draw that reset either would break the pass around it.
|
|
5511
5681
|
*/
|
|
5682
|
+
/* Taken for itself when any option differs from the pass, and put back below: the rule both
|
|
5683
|
+
backends count material changes by. See `materialChanges.ts`. */
|
|
5684
|
+
const own = ownsMaterial({ opacity, lit, fog, toneMapped, refracting });
|
|
5685
|
+
if (own)
|
|
5686
|
+
this.materials.dirty();
|
|
5687
|
+
this.takeMaterial();
|
|
5512
5688
|
const ownsState = !this.oitReplaying;
|
|
5513
5689
|
if (ownsState) {
|
|
5514
5690
|
gl.enable(gl.BLEND);
|
|
@@ -5550,6 +5726,8 @@ export class WebGL2Renderer {
|
|
|
5550
5726
|
gl.uniform1i(u['uFogEnabled'] ?? null, 1);
|
|
5551
5727
|
if (!toneMapped)
|
|
5552
5728
|
gl.uniform1i(u['uOutputTransform'] ?? null, this.gradeCode());
|
|
5729
|
+
if (own)
|
|
5730
|
+
this.materials.dirty();
|
|
5553
5731
|
}
|
|
5554
5732
|
/**
|
|
5555
5733
|
* Capture the room into a cubemap, once, so reflective surfaces can mirror it.
|
|
@@ -5647,6 +5825,23 @@ export class WebGL2Renderer {
|
|
|
5647
5825
|
this.useFlatProgram();
|
|
5648
5826
|
this.gl.uniform1i(this.flatUniforms['uOutputTransform'] ?? null, 0);
|
|
5649
5827
|
this.gl.uniform1f(this.flatUniforms['uOutputExposure'] ?? null, 1);
|
|
5828
|
+
this.materials.dirty();
|
|
5829
|
+
/*
|
|
5830
|
+
* **Clockwise for the duration, because a face is rendered mirrored.** `cubeFaceProjection`
|
|
5831
|
+
* negates clip y so the face is stored the way a cubemap reads it, and negating one axis
|
|
5832
|
+
* reverses every triangle's winding: without this the room is culled inside out and the cube
|
|
5833
|
+
* holds its own back faces.
|
|
5834
|
+
*
|
|
5835
|
+
* **A perturbation survives this line and it is kept anyway**, which is worth the sentence.
|
|
5836
|
+
* Deleting it moves `ibl-check.mjs`'s figures — 12.5 to 13.1 of 255 on the movement check and
|
|
5837
|
+
* 182.0 to 184.9 on the mirror rung — so it is not dead; but no check *fails*, because every
|
|
5838
|
+
* room this repository bakes into a probe is made of closed boxes whose two sides carry the
|
|
5839
|
+
* same colour, and looking at the far one's outside instead of the near one's inside draws
|
|
5840
|
+
* almost the same picture. What it actually decides is a scene with **one-sided** geometry: a
|
|
5841
|
+
* room built from single quads facing inward disappears from its own probe without it, and
|
|
5842
|
+
* there is no such scene here to fail on.
|
|
5843
|
+
*/
|
|
5844
|
+
this.gl.frontFace(this.gl.CW);
|
|
5650
5845
|
let baked = false;
|
|
5651
5846
|
try {
|
|
5652
5847
|
baked = probe.bake(this.gl, this.probeOrigin, clearColor, drawFace);
|
|
@@ -5660,9 +5855,11 @@ export class WebGL2Renderer {
|
|
|
5660
5855
|
}
|
|
5661
5856
|
}
|
|
5662
5857
|
finally {
|
|
5858
|
+
this.gl.frontFace(this.gl.CCW);
|
|
5663
5859
|
this.useFlatProgram();
|
|
5664
5860
|
this.gl.uniform1i(this.flatUniforms['uOutputTransform'] ?? null, this.gradeCode());
|
|
5665
5861
|
this.gl.uniform1f(this.flatUniforms['uOutputExposure'] ?? null, this.gradeExposure());
|
|
5862
|
+
this.materials.dirty();
|
|
5666
5863
|
/*
|
|
5667
5864
|
* Cleared even if a caller's own draw threw, because leaving this set would keep every
|
|
5668
5865
|
* later frame reading the placeholder and quietly reflecting nothing.
|
|
@@ -5804,6 +6001,7 @@ export class WebGL2Renderer {
|
|
|
5804
6001
|
where the beam has no medium to be seen in and skipping it is the whole saving. */
|
|
5805
6002
|
if (shown <= 0)
|
|
5806
6003
|
return;
|
|
6004
|
+
this.lightVolumeBudget.ask();
|
|
5807
6005
|
const { gl } = this;
|
|
5808
6006
|
const u = this.lightVolumeUniforms;
|
|
5809
6007
|
gl.useProgram(this.lightVolumeProgram);
|
|
@@ -27,8 +27,27 @@ export interface VertexAttribute {
|
|
|
27
27
|
export declare const VERTEX_LAYOUT: readonly VertexAttribute[];
|
|
28
28
|
/** Geometry on the device, with the buffers bound in layout order. */
|
|
29
29
|
export interface GpuMesh {
|
|
30
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* The buffers a draw binds, in the order `vertexBufferLayouts` describes them.
|
|
32
|
+
*
|
|
33
|
+
* **Two, and the first is interleaved** — every attribute this mesh actually supplied, woven
|
|
34
|
+
* into one stride — while the second holds one value per *absent* optional attribute at a stride
|
|
35
|
+
* of zero. It is emphatically not one buffer per attribute, which this comment said until
|
|
36
|
+
* 2026-09-17 and which cost the motion pass an afternoon: a pipeline built to that description
|
|
37
|
+
* reads a position out of every twelve bytes of an interleaved vertex, draws geometry that is
|
|
38
|
+
* not the mesh, and fails no validation at all.
|
|
39
|
+
*/
|
|
31
40
|
readonly vertexBuffers: readonly GPUBuffer[];
|
|
41
|
+
/**
|
|
42
|
+
* Bytes a vertex takes in the first of those buffers.
|
|
43
|
+
*
|
|
44
|
+
* Kept because it is a function of which *optional* attributes this mesh supplied, so it differs
|
|
45
|
+
* between two meshes drawn by the same pipeline — and a pass that reads only the position still
|
|
46
|
+
* has to step by the whole of it. `submitMesh` never needs it, the generated pipelines being
|
|
47
|
+
* keyed by the same `present` map that decides it; anything drawing a mesh through a shader of
|
|
48
|
+
* its own does.
|
|
49
|
+
*/
|
|
50
|
+
readonly vertexStride: number;
|
|
32
51
|
readonly indexBuffer: GPUBuffer;
|
|
33
52
|
readonly indexCount: number;
|
|
34
53
|
/**
|