@driftengine/core 4.4.2 → 4.6.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 +97 -0
- package/README.md +1 -1
- package/dist/geometry/boxCsg.d.ts +28 -0
- package/dist/geometry/boxCsg.js +139 -0
- package/dist/geometry/csg.d.ts +36 -0
- package/dist/geometry/csg.js +329 -0
- package/dist/geometry/meshBuilder.js +13 -0
- package/dist/geometry/meshConcat.js +1 -0
- package/dist/geometry/pixelFont.js +2 -0
- package/dist/geometry/solid.d.ts +61 -0
- package/dist/geometry/solid.js +152 -0
- package/dist/geometry/solidFlat.d.ts +35 -0
- package/dist/geometry/solidFlat.js +428 -0
- package/dist/geometry/solidHarness.d.ts +19 -0
- package/dist/geometry/solidHarness.js +66 -0
- package/dist/geometry/solidNormals.d.ts +17 -0
- package/dist/geometry/solidNormals.js +86 -0
- package/dist/geometry/solidRound.d.ts +41 -0
- package/dist/geometry/solidRound.js +323 -0
- package/dist/geometry/solidWriter.d.ts +16 -0
- package/dist/geometry/solidWriter.js +42 -0
- package/dist/index.d.ts +28 -3
- package/dist/index.js +20 -1
- package/dist/render/backend/api.d.ts +34 -14
- package/dist/render/backend/drawFog.d.ts +26 -0
- package/dist/render/backend/drawFog.js +30 -0
- package/dist/render/backend/materialChanges.d.ts +2 -1
- package/dist/render/backend/materialChanges.js +6 -1
- package/dist/render/backend/webgl2/glassTintPrograms.d.ts +13 -0
- package/dist/render/backend/webgl2/glassTintPrograms.js +38 -0
- package/dist/render/backend/webgl2/instanced.d.ts +24 -5
- package/dist/render/backend/webgl2/instanced.js +72 -15
- package/dist/render/backend/webgl2/renderer.d.ts +201 -16
- package/dist/render/backend/webgl2/renderer.js +596 -224
- package/dist/render/backend/webgpu/buffers.d.ts +29 -1
- package/dist/render/backend/webgpu/buffers.js +61 -4
- package/dist/render/backend/webgpu/depthPass.d.ts +1 -1
- package/dist/render/backend/webgpu/depthPass.js +7 -2
- package/dist/render/backend/webgpu/drawCommand.d.ts +5 -0
- package/dist/render/backend/webgpu/drawCommand.js +1 -0
- package/dist/render/backend/webgpu/flatPass.d.ts +6 -1
- package/dist/render/backend/webgpu/flatPass.js +57 -9
- package/dist/render/backend/webgpu/glassTintPass.d.ts +28 -0
- package/dist/render/backend/webgpu/glassTintPass.js +206 -0
- package/dist/render/backend/webgpu/gpuDrivenPass.d.ts +60 -1
- package/dist/render/backend/webgpu/gpuDrivenPass.js +305 -5
- package/dist/render/backend/webgpu/instanceCullPass.d.ts +34 -0
- package/dist/render/backend/webgpu/instanceCullPass.js +144 -0
- package/dist/render/backend/webgpu/instanced.d.ts +23 -2
- package/dist/render/backend/webgpu/instanced.js +41 -4
- package/dist/render/backend/webgpu/latePass.d.ts +30 -0
- package/dist/render/backend/webgpu/latePass.js +140 -0
- package/dist/render/backend/webgpu/lightVolumePass.js +5 -1
- package/dist/render/backend/webgpu/motionPass.d.ts +95 -0
- package/dist/render/backend/webgpu/motionPass.js +491 -0
- package/dist/render/backend/webgpu/pipelineCache.d.ts +10 -1
- package/dist/render/backend/webgpu/pipelineCache.js +11 -1
- package/dist/render/backend/webgpu/pointGlassTintPass.d.ts +32 -0
- package/dist/render/backend/webgpu/pointGlassTintPass.js +193 -0
- package/dist/render/backend/webgpu/pointShadowPass.d.ts +35 -6
- package/dist/render/backend/webgpu/pointShadowPass.js +105 -20
- package/dist/render/backend/webgpu/postPass.d.ts +3 -13
- package/dist/render/backend/webgpu/renderer.d.ts +271 -64
- package/dist/render/backend/webgpu/renderer.js +1395 -580
- package/dist/render/backend/webgpu/scatterPass.js +2 -1
- package/dist/render/backend/webgpu/sdfTextPass.js +6 -1
- package/dist/render/backend/webgpu/shaders/instanceCull.wgsl.d.ts +18 -0
- package/dist/render/backend/webgpu/shaders/instanceCull.wgsl.js +59 -0
- package/dist/render/backend/webgpu/skinPaletteRing.d.ts +4 -0
- package/dist/render/backend/webgpu/skinPaletteRing.js +4 -0
- package/dist/render/backend/webgpu/snapshotMips.d.ts +29 -0
- package/dist/render/backend/webgpu/snapshotMips.js +52 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +22 -3
- package/dist/render/backend/webgpu/surfaceTexturePass.js +78 -39
- package/dist/render/driftLight/bake.d.ts +7 -0
- package/dist/render/driftLight/bake.js +61 -56
- package/dist/render/driftLight/denseField.d.ts +46 -0
- package/dist/render/driftLight/denseField.js +109 -0
- package/dist/render/driftLight/lightField.d.ts +10 -5
- package/dist/render/driftLight/lightField.js +25 -19
- package/dist/render/driftLight/presence.d.ts +50 -0
- package/dist/render/driftLight/presence.js +43 -0
- package/dist/render/driftLight/uniforms.d.ts +3 -3
- package/dist/render/driftLight/uniforms.js +5 -6
- package/dist/render/driftLight/worldLightField.d.ts +41 -0
- package/dist/render/driftLight/worldLightField.js +66 -0
- package/dist/render/fixtureAtlas.d.ts +20 -0
- package/dist/render/fixtureAtlas.js +49 -0
- package/dist/render/glass.d.ts +45 -0
- package/dist/render/glass.js +39 -0
- package/dist/render/glassCasters.d.ts +40 -0
- package/dist/render/glassCasters.js +84 -0
- package/dist/render/glassShadow.d.ts +78 -0
- package/dist/render/glassShadow.js +125 -0
- package/dist/render/globalMediumPass.d.ts +2 -3
- package/dist/render/globalMediumPass.js +2 -8
- package/dist/render/gpudriven/lit.d.ts +12 -0
- package/dist/render/gpudriven/lit.js +23 -0
- package/dist/render/gpudriven/materialTable.d.ts +15 -5
- package/dist/render/gpudriven/materialTable.js +26 -6
- package/dist/render/gpudriven/pipeline.d.ts +1 -1
- package/dist/render/gpudriven/pipeline.js +4 -3
- package/dist/render/gpudriven/sunGlass.d.ts +35 -0
- package/dist/render/gpudriven/sunGlass.js +89 -0
- package/dist/render/instanceCull.d.ts +63 -0
- package/dist/render/instanceCull.js +160 -0
- package/dist/render/instances.d.ts +15 -0
- package/dist/render/lightBudget.d.ts +36 -35
- package/dist/render/lightBudget.js +38 -37
- package/dist/render/lightGrid.d.ts +42 -0
- package/dist/render/lightGrid.js +87 -0
- package/dist/render/mesh.d.ts +18 -24
- package/dist/render/mesh.js +51 -68
- package/dist/render/occlusion.d.ts +10 -0
- package/dist/render/occlusion.js +36 -7
- package/dist/render/pointGlassTint.d.ts +59 -0
- package/dist/render/pointGlassTint.js +198 -0
- package/dist/render/pointLightSelection.d.ts +7 -0
- package/dist/render/pointLightSelection.js +29 -4
- package/dist/render/pointShadowArray.d.ts +56 -3
- package/dist/render/pointShadowArray.js +127 -16
- package/dist/render/pointShadowMap.d.ts +23 -1
- package/dist/render/pointShadowMap.js +27 -1
- package/dist/render/rainField.d.ts +13 -0
- package/dist/render/rainField.js +27 -5
- package/dist/render/recon/changeFrames.d.ts +15 -0
- package/dist/render/recon/changeFrames.js +21 -0
- package/dist/render/recon/lateDepth.d.ts +11 -0
- package/dist/render/recon/lateDepth.js +70 -0
- package/dist/render/recon/lateRouting.d.ts +14 -0
- package/dist/render/recon/lateRouting.js +18 -0
- package/dist/render/recon/mover.d.ts +57 -0
- package/dist/render/recon/mover.js +86 -0
- package/dist/render/recon/resolve.d.ts +34 -4
- package/dist/render/recon/resolve.js +161 -20
- package/dist/render/renderQuality.d.ts +35 -0
- package/dist/render/renderQuality.js +7 -0
- package/dist/render/rendererHarness.js +16 -0
- package/dist/render/sceneTarget.d.ts +9 -1
- package/dist/render/sceneTarget.js +60 -12
- package/dist/render/shaders/depth.d.ts +16 -1
- package/dist/render/shaders/depth.js +94 -15
- package/dist/render/shaders/flat/directionalShadow.js +91 -6
- package/dist/render/shaders/flat/driftLight.d.ts +1 -1
- package/dist/render/shaders/flat/driftLight.js +32 -7
- package/dist/render/shaders/flat/glassTint.d.ts +6 -0
- package/dist/render/shaders/flat/glassTint.js +25 -0
- package/dist/render/shaders/flat/index.d.ts +13 -0
- package/dist/render/shaders/flat/index.js +9 -3
- package/dist/render/shaders/flat/lampGlass.d.ts +1 -0
- package/dist/render/shaders/flat/lampGlass.js +183 -0
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +190 -38
- package/dist/render/shaders/flat/pointShadow.d.ts +1 -1
- package/dist/render/shaders/flat/pointShadow.js +2 -0
- package/dist/render/shaders/flat/preamble.js +96 -26
- package/dist/render/shaders/flat/surfaceEffects.d.ts +29 -0
- package/dist/render/shaders/flat/surfaceEffects.js +152 -0
- package/dist/render/shaders/generated/depth.wgsl.d.ts +230 -7
- package/dist/render/shaders/generated/depth.wgsl.js +230 -7
- package/dist/render/shaders/generated/flat.wgsl.d.ts +1644 -1596
- package/dist/render/shaders/generated/flat.wgsl.js +1683 -1621
- package/dist/render/shaders/generated/globalMedium.wgsl.d.ts +3 -13
- package/dist/render/shaders/generated/globalMedium.wgsl.js +3 -13
- package/dist/render/shaders/generated/lightVolume.wgsl.d.ts +3 -13
- package/dist/render/shaders/generated/lightVolume.wgsl.js +21 -17
- package/dist/render/shaders/generated/octahedralResolve.wgsl.d.ts +29 -0
- package/dist/render/shaders/generated/octahedralResolve.wgsl.js +29 -0
- package/dist/render/shaders/generated/rush.wgsl.d.ts +21 -16
- package/dist/render/shaders/generated/rush.wgsl.js +21 -16
- package/dist/render/shaders/generated/sdfText.wgsl.d.ts +2 -2
- package/dist/render/shaders/generated/sdfText.wgsl.js +2 -2
- package/dist/render/shaders/generated/text.wgsl.d.ts +1 -1
- package/dist/render/shaders/generated/text.wgsl.js +1 -1
- package/dist/render/shaders/gi/driftLight.wgsl.d.ts +1 -1
- package/dist/render/shaders/gi/driftLight.wgsl.js +27 -4
- package/dist/render/shaders/globalMedium.js +6 -6
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.d.ts +7 -0
- package/dist/render/shaders/gpudriven/blendRaster.wgsl.js +86 -1
- package/dist/render/shaders/gpudriven/cull.wgsl.d.ts +1 -1
- package/dist/render/shaders/gpudriven/cull.wgsl.js +11 -2
- package/dist/render/shaders/gpudriven/materialTable.wgsl.d.ts +1 -1
- package/dist/render/shaders/gpudriven/materialTable.wgsl.js +3 -1
- package/dist/render/shaders/gpudriven/shade.wgsl.js +50 -1
- package/dist/render/shaders/gpudriven/sunGlass.wgsl.d.ts +9 -0
- package/dist/render/shaders/gpudriven/sunGlass.wgsl.js +133 -0
- package/dist/render/shaders/lightVolume.js +6 -6
- package/dist/render/shaders/octahedralResolve.d.ts +8 -0
- package/dist/render/shaders/octahedralResolve.js +48 -17
- package/dist/render/shaders/recon/lateDepth.wgsl.d.ts +1 -0
- package/dist/render/shaders/recon/lateDepth.wgsl.js +69 -0
- package/dist/render/shaders/recon/motion.wgsl.d.ts +1 -1
- package/dist/render/shaders/recon/motion.wgsl.js +84 -0
- package/dist/render/shaders/recon/resolve.wgsl.d.ts +8 -7
- package/dist/render/shaders/recon/resolve.wgsl.js +161 -27
- package/dist/render/shaders/rush.js +11 -1
- package/dist/render/shaders/sdfText.d.ts +1 -1
- package/dist/render/shaders/sdfText.js +3 -2
- package/dist/render/shaders/text.d.ts +1 -1
- package/dist/render/shaders/text.js +18 -9
- package/dist/render/shadowCasters.d.ts +20 -1
- package/dist/render/shadowCasters.js +15 -1
- package/dist/render/shadowMap.d.ts +54 -5
- package/dist/render/shadowMap.js +190 -36
- package/dist/render/sunGlassTint.d.ts +25 -0
- package/dist/render/sunGlassTint.js +79 -0
- package/dist/render/surfaceEffects.d.ts +83 -0
- package/dist/render/surfaceEffects.js +75 -0
- package/dist/render/surfaceScene.d.ts +8 -0
- package/dist/render/surfaceScene.js +8 -0
- package/dist/render/surfaceTexture.d.ts +18 -2
- package/dist/render/surfaceTexture.js +68 -15
- package/dist/render/temporalAa.d.ts +25 -6
- package/dist/render/temporalAa.js +45 -15
- package/dist/render/textureSource.d.ts +30 -0
- package/dist/render/textureSource.js +53 -0
- package/dist/render/translucentQueue.d.ts +6 -0
- package/dist/render/translucentQueue.js +15 -1
- package/dist/render/vertexDefaults.js +2 -0
- package/dist/world/hlod.d.ts +104 -0
- package/dist/world/hlod.js +214 -0
- package/package.json +6 -6
- package/src/geometry/boxCsg.ts +186 -0
- package/src/geometry/csg.ts +384 -0
- package/src/geometry/meshBuilder.ts +15 -0
- package/src/geometry/meshConcat.ts +1 -0
- package/src/geometry/pixelFont.ts +2 -0
- package/src/geometry/solid.ts +189 -0
- package/src/geometry/solidFlat.ts +522 -0
- package/src/geometry/solidHarness.ts +83 -0
- package/src/geometry/solidNormals.ts +103 -0
- package/src/geometry/solidRound.ts +443 -0
- package/src/geometry/solidWriter.ts +58 -0
- package/src/index.ts +61 -1
- package/src/render/backend/api.ts +36 -11
- package/src/render/backend/drawFog.ts +31 -0
- package/src/render/backend/materialChanges.ts +9 -2
- package/src/render/backend/webgl2/glassTintPrograms.ts +58 -0
- package/src/render/backend/webgl2/instanced.ts +80 -14
- package/src/render/backend/webgl2/renderer.ts +700 -250
- package/src/render/backend/webgpu/buffers.ts +92 -5
- package/src/render/backend/webgpu/depthPass.ts +7 -2
- package/src/render/backend/webgpu/drawCommand.ts +6 -0
- package/src/render/backend/webgpu/flatPass.ts +62 -11
- package/src/render/backend/webgpu/glassTintPass.ts +245 -0
- package/src/render/backend/webgpu/gpuDrivenPass.ts +349 -5
- package/src/render/backend/webgpu/instanceCullPass.ts +165 -0
- package/src/render/backend/webgpu/instanced.ts +42 -4
- package/src/render/backend/webgpu/latePass.ts +161 -0
- package/src/render/backend/webgpu/lightVolumePass.ts +5 -1
- package/src/render/backend/webgpu/motionPass.ts +535 -0
- package/src/render/backend/webgpu/pipelineCache.ts +12 -1
- package/src/render/backend/webgpu/pointGlassTintPass.ts +233 -0
- package/src/render/backend/webgpu/pointShadowPass.ts +158 -26
- package/src/render/backend/webgpu/renderer.ts +1671 -670
- package/src/render/backend/webgpu/scatterPass.ts +2 -1
- package/src/render/backend/webgpu/sdfTextPass.ts +6 -1
- package/src/render/backend/webgpu/shaders/instanceCull.wgsl.ts +61 -0
- package/src/render/backend/webgpu/skinPaletteRing.ts +4 -0
- package/src/render/backend/webgpu/snapshotMips.ts +80 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +91 -51
- package/src/render/driftLight/bake.ts +85 -62
- package/src/render/driftLight/denseField.ts +149 -0
- package/src/render/driftLight/lightField.ts +33 -18
- package/src/render/driftLight/presence.ts +69 -0
- package/src/render/driftLight/uniforms.ts +8 -9
- package/src/render/driftLight/worldLightField.ts +83 -0
- package/src/render/fixtureAtlas.ts +63 -0
- package/src/render/glass.ts +74 -0
- package/src/render/glassCasters.ts +164 -0
- package/src/render/glassShadow.ts +153 -0
- package/src/render/globalMediumPass.ts +4 -11
- package/src/render/gpudriven/lit.ts +31 -0
- package/src/render/gpudriven/materialTable.ts +28 -6
- package/src/render/gpudriven/pipeline.ts +4 -3
- package/src/render/gpudriven/sunGlass.ts +117 -0
- package/src/render/instanceCull.ts +205 -0
- package/src/render/instances.ts +16 -0
- package/src/render/lightBudget.ts +41 -38
- package/src/render/lightGrid.ts +130 -0
- package/src/render/mesh.ts +59 -72
- package/src/render/occlusion.ts +51 -7
- package/src/render/pointGlassTint.ts +250 -0
- package/src/render/pointLightSelection.ts +72 -4
- package/src/render/pointShadowArray.ts +188 -22
- package/src/render/pointShadowMap.ts +41 -0
- package/src/render/rainField.ts +39 -5
- package/src/render/recon/changeFrames.ts +24 -0
- package/src/render/recon/lateDepth.ts +83 -0
- package/src/render/recon/lateRouting.ts +29 -0
- package/src/render/recon/mover.ts +118 -0
- package/src/render/recon/resolve.ts +206 -20
- package/src/render/renderQuality.ts +47 -0
- package/src/render/rendererHarness.ts +16 -0
- package/src/render/sceneTarget.ts +62 -11
- package/src/render/shaders/depth.ts +118 -15
- package/src/render/shaders/flat/directionalShadow.ts +97 -6
- package/src/render/shaders/flat/driftLight.ts +32 -7
- package/src/render/shaders/flat/glassTint.ts +25 -0
- package/src/render/shaders/flat/index.ts +22 -3
- package/src/render/shaders/flat/lampGlass.ts +185 -0
- package/src/render/shaders/flat/main.ts +190 -38
- package/src/render/shaders/flat/pointShadow.ts +2 -0
- package/src/render/shaders/flat/preamble.ts +96 -26
- package/src/render/shaders/flat/surfaceEffects.ts +152 -0
- package/src/render/shaders/generated/depth.wgsl.ts +237 -7
- package/src/render/shaders/generated/flat.wgsl.ts +1685 -1621
- package/src/render/shaders/generated/globalMedium.wgsl.ts +3 -13
- package/src/render/shaders/generated/lightVolume.wgsl.ts +23 -17
- package/src/render/shaders/generated/octahedralResolve.wgsl.ts +30 -0
- package/src/render/shaders/generated/rush.wgsl.ts +21 -16
- package/src/render/shaders/generated/sdfText.wgsl.ts +2 -2
- package/src/render/shaders/generated/text.wgsl.ts +1 -1
- package/src/render/shaders/gi/driftLight.wgsl.ts +27 -4
- package/src/render/shaders/globalMedium.ts +6 -6
- package/src/render/shaders/gpudriven/blendRaster.wgsl.ts +88 -1
- package/src/render/shaders/gpudriven/cull.wgsl.ts +11 -2
- package/src/render/shaders/gpudriven/materialTable.wgsl.ts +3 -1
- package/src/render/shaders/gpudriven/shade.wgsl.ts +50 -1
- package/src/render/shaders/gpudriven/sunGlass.wgsl.ts +139 -0
- package/src/render/shaders/lightVolume.ts +6 -6
- package/src/render/shaders/octahedralResolve.ts +50 -17
- package/src/render/shaders/recon/lateDepth.wgsl.ts +72 -0
- package/src/render/shaders/recon/motion.wgsl.ts +84 -0
- package/src/render/shaders/recon/resolve.wgsl.ts +161 -27
- package/src/render/shaders/rush.ts +11 -1
- package/src/render/shaders/sdfText.ts +3 -2
- package/src/render/shaders/text.ts +18 -9
- package/src/render/shadowCasters.ts +28 -1
- package/src/render/shadowMap.ts +231 -37
- package/src/render/sunGlassTint.ts +86 -0
- package/src/render/surfaceEffects.ts +132 -0
- package/src/render/surfaceScene.ts +16 -0
- package/src/render/surfaceTexture.ts +110 -19
- package/src/render/temporalAa.ts +78 -14
- package/src/render/textureSource.ts +72 -0
- package/src/render/translucentQueue.ts +20 -1
- package/src/render/vertexDefaults.ts +2 -0
- package/src/world/hlod.ts +290 -0
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where every mover was last frame, drawn into the reconstruction's motion target.
|
|
3
|
+
*
|
|
4
|
+
* Moved out of `renderer.ts` when it grew variants: the renderer decides *which* draws moved and
|
|
5
|
+
* hands them here; this owns how their motion is drawn. See `shaders/recon/motion.wgsl.ts` for what
|
|
6
|
+
* a texel carries, why it is a pass of its own, and why its matrices are unjittered.
|
|
7
|
+
*/
|
|
8
|
+
import { DEPTH_COMPARE_EQUAL, DEPTH_FORMAT } from '../../depthConvention.js';
|
|
9
|
+
import { MOTION_DRAW_FLOATS, MOTION_DRAW_STRIDE, MOTION_FRAME_FLOATS, MOTION_TARGET_FORMAT, RECON_MOTION_WGSL, } from '../../shaders/recon/motion.wgsl.js';
|
|
10
|
+
import { INSTANCE_STRIDE } from '../../instances.js';
|
|
11
|
+
/** What a record is, which decides the vertex stage and what else it binds. */
|
|
12
|
+
const RIGID = 0;
|
|
13
|
+
const SKINNED = 1;
|
|
14
|
+
const DYNAMIC = 2;
|
|
15
|
+
const INSTANCED = 3;
|
|
16
|
+
/** An instanced record's per-draw matrices are not read; this fills their slot. */
|
|
17
|
+
const IDENTITY = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
|
|
18
|
+
export class MotionPass {
|
|
19
|
+
device;
|
|
20
|
+
/** The frame's movers, in the order they were drawn. */
|
|
21
|
+
meshes = [];
|
|
22
|
+
/** Two matrices a mover — this frame's model and last frame's — at `MOTION_DRAW_FLOATS` apart. */
|
|
23
|
+
matrices = new Float32Array(0);
|
|
24
|
+
count = 0;
|
|
25
|
+
/** `RIGID` or `SKINNED` per record, grown beside `matrices`. */
|
|
26
|
+
kinds = new Uint8Array(0);
|
|
27
|
+
/** A skinned record's two palettes, this frame's and last frame's, by record index. */
|
|
28
|
+
paletteNow = [];
|
|
29
|
+
paletteWas = [];
|
|
30
|
+
/** A rewritten record's last-frame rows, by record index. */
|
|
31
|
+
previousRows = [];
|
|
32
|
+
/** One pipeline per stride for rewritten meshes: current and previous rows at that stride. */
|
|
33
|
+
dynamicPipelines = new Map();
|
|
34
|
+
/** An instanced record's placement this frame and last frame, and how many slots pair. */
|
|
35
|
+
instancesNow = [];
|
|
36
|
+
instancesWas = [];
|
|
37
|
+
instanceCounts = new Uint32Array(0);
|
|
38
|
+
instancedPipelines = new Map();
|
|
39
|
+
layout = null;
|
|
40
|
+
paletteLayout = null;
|
|
41
|
+
skinnedLayout = null;
|
|
42
|
+
/** Keyed by stride and the two skin offsets, packed into one number so a lookup builds nothing. */
|
|
43
|
+
skinnedPipelines = new Map();
|
|
44
|
+
/**
|
|
45
|
+
* A bind group per pair of palette views. The ring keeps its textures from frame to frame, so a
|
|
46
|
+
* steady scene settles on a handful of pairs and builds nothing per frame.
|
|
47
|
+
*/
|
|
48
|
+
paletteGroups = new Map();
|
|
49
|
+
module = null;
|
|
50
|
+
pipelineLayout = null;
|
|
51
|
+
pipelines = new Map();
|
|
52
|
+
frameBuffer = null;
|
|
53
|
+
drawBuffer = null;
|
|
54
|
+
drawCapacity = 0;
|
|
55
|
+
group = null;
|
|
56
|
+
frameStaging = new Float32Array(MOTION_FRAME_FLOATS);
|
|
57
|
+
drawStaging = new Uint8Array(0);
|
|
58
|
+
/** A float view of `drawStaging`, made when it is, so a frame's upload allocates nothing. */
|
|
59
|
+
drawFloats = new Float32Array(0);
|
|
60
|
+
constructor(device) {
|
|
61
|
+
this.device = device;
|
|
62
|
+
}
|
|
63
|
+
/** A frame states its movers afresh. */
|
|
64
|
+
reset() {
|
|
65
|
+
this.count = 0;
|
|
66
|
+
}
|
|
67
|
+
/** A rigid mover: the same positions under last frame's model. */
|
|
68
|
+
recordRigid(mesh, model, previousModel) {
|
|
69
|
+
this.take(mesh, model, previousModel, RIGID);
|
|
70
|
+
}
|
|
71
|
+
/** A skinned mover: its positions under last frame's pose as well as last frame's model. */
|
|
72
|
+
recordSkinned(mesh, model, previousModel, palette, previousPalette) {
|
|
73
|
+
const at = this.take(mesh, model, previousModel, SKINNED);
|
|
74
|
+
this.paletteNow[at] = palette;
|
|
75
|
+
this.paletteWas[at] = previousPalette;
|
|
76
|
+
}
|
|
77
|
+
/** A rewritten mesh: its vertices as they were, read from `previous`, under last frame's model. */
|
|
78
|
+
recordDynamic(mesh, model, previousModel, previous) {
|
|
79
|
+
const at = this.take(mesh, model, previousModel, DYNAMIC);
|
|
80
|
+
this.previousRows[at] = previous;
|
|
81
|
+
}
|
|
82
|
+
/** An instanced batch: its first `count` slots, each under last frame's placement of that slot. */
|
|
83
|
+
recordInstanced(mesh, placement, previousPlacement, count) {
|
|
84
|
+
const at = this.take(mesh, IDENTITY, IDENTITY, INSTANCED);
|
|
85
|
+
this.instancesNow[at] = placement;
|
|
86
|
+
this.instancesWas[at] = previousPlacement;
|
|
87
|
+
this.instanceCounts[at] = count;
|
|
88
|
+
}
|
|
89
|
+
/** One record's slot: its mesh, its two matrices and its kind. Returns the record's index. */
|
|
90
|
+
take(mesh, model, previousModel, kind) {
|
|
91
|
+
const at = this.count;
|
|
92
|
+
const wanted = (at + 1) * MOTION_DRAW_FLOATS;
|
|
93
|
+
if (this.matrices.length < wanted) {
|
|
94
|
+
/* Doubling, so a scene settles on one allocation rather than one a draw. */
|
|
95
|
+
const grown = new Float32Array(Math.max(wanted, this.matrices.length * 2, 64));
|
|
96
|
+
grown.set(this.matrices);
|
|
97
|
+
this.matrices = grown;
|
|
98
|
+
const kinds = new Uint8Array(grown.length / MOTION_DRAW_FLOATS);
|
|
99
|
+
kinds.set(this.kinds);
|
|
100
|
+
this.kinds = kinds;
|
|
101
|
+
const counts = new Uint32Array(kinds.length);
|
|
102
|
+
counts.set(this.instanceCounts);
|
|
103
|
+
this.instanceCounts = counts;
|
|
104
|
+
}
|
|
105
|
+
this.matrices.set(model, at * MOTION_DRAW_FLOATS);
|
|
106
|
+
this.matrices.set(previousModel, at * MOTION_DRAW_FLOATS + 16);
|
|
107
|
+
this.meshes[at] = mesh;
|
|
108
|
+
this.kinds[at] = kind;
|
|
109
|
+
this.count = at + 1;
|
|
110
|
+
return at;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The pipeline layout and module, built once.
|
|
114
|
+
*
|
|
115
|
+
* **The position alone**, at offset zero of the mesh's interleaved rows: that is all the rigid
|
|
116
|
+
* stage reads, and positions are the layout's first attribute and never optional.
|
|
117
|
+
*/
|
|
118
|
+
buildLayout() {
|
|
119
|
+
if (this.layout !== null)
|
|
120
|
+
return;
|
|
121
|
+
this.layout = this.device.createBindGroupLayout({
|
|
122
|
+
label: 'recon.motion.layout',
|
|
123
|
+
entries: [
|
|
124
|
+
{ binding: 0, visibility: 0x1, buffer: { type: 'uniform' } },
|
|
125
|
+
{
|
|
126
|
+
binding: 1,
|
|
127
|
+
visibility: 0x1,
|
|
128
|
+
buffer: { type: 'uniform', hasDynamicOffset: true },
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
});
|
|
132
|
+
this.module = this.device.createShaderModule({
|
|
133
|
+
label: 'recon.motion',
|
|
134
|
+
code: RECON_MOTION_WGSL,
|
|
135
|
+
});
|
|
136
|
+
this.pipelineLayout = this.device.createPipelineLayout({
|
|
137
|
+
bindGroupLayouts: [this.layout],
|
|
138
|
+
});
|
|
139
|
+
/* The two palettes, read with `textureLoad` at integer texels: unfilterable is exact. */
|
|
140
|
+
this.paletteLayout = this.device.createBindGroupLayout({
|
|
141
|
+
label: 'recon.motion.palettes',
|
|
142
|
+
entries: [
|
|
143
|
+
{ binding: 0, visibility: 0x1, texture: { sampleType: 'unfilterable-float' } },
|
|
144
|
+
{ binding: 1, visibility: 0x1, texture: { sampleType: 'unfilterable-float' } },
|
|
145
|
+
],
|
|
146
|
+
});
|
|
147
|
+
this.skinnedLayout = this.device.createPipelineLayout({
|
|
148
|
+
bindGroupLayouts: [this.layout, this.paletteLayout],
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* The skinned pipeline for one stride and one placement of the joints and weights in it.
|
|
153
|
+
*
|
|
154
|
+
* Same fragment stage, winding and depth test as the rigid one — see `pipelineFor` — with the two
|
|
155
|
+
* skinning attributes read from the interleaved rows at the offsets the mesh records.
|
|
156
|
+
*/
|
|
157
|
+
skinnedPipelineFor(stride, offsets) {
|
|
158
|
+
const key = (stride * 4096 + offsets.joints) * 4096 + offsets.weights;
|
|
159
|
+
const held = this.skinnedPipelines.get(key);
|
|
160
|
+
if (held !== undefined)
|
|
161
|
+
return held;
|
|
162
|
+
const module = this.module;
|
|
163
|
+
const layout = this.skinnedLayout;
|
|
164
|
+
if (module === null || layout === null)
|
|
165
|
+
return null;
|
|
166
|
+
const pipeline = this.device.createRenderPipeline({
|
|
167
|
+
label: `recon.motion.skinned.${String(stride)}`,
|
|
168
|
+
layout,
|
|
169
|
+
vertex: {
|
|
170
|
+
module,
|
|
171
|
+
entryPoint: 'motionSkinnedVert',
|
|
172
|
+
buffers: [
|
|
173
|
+
{
|
|
174
|
+
arrayStride: stride,
|
|
175
|
+
attributes: [
|
|
176
|
+
{ shaderLocation: 0, offset: 0, format: 'float32x3' },
|
|
177
|
+
{ shaderLocation: 11, offset: offsets.joints, format: 'float32x4' },
|
|
178
|
+
{ shaderLocation: 12, offset: offsets.weights, format: 'float32x4' },
|
|
179
|
+
],
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
fragment: { module, entryPoint: 'motionFrag', targets: [{ format: MOTION_TARGET_FORMAT }] },
|
|
184
|
+
primitive: { topology: 'triangle-list', cullMode: 'back' },
|
|
185
|
+
depthStencil: {
|
|
186
|
+
format: DEPTH_FORMAT,
|
|
187
|
+
depthWriteEnabled: false,
|
|
188
|
+
depthCompare: DEPTH_COMPARE_EQUAL,
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
this.skinnedPipelines.set(key, pipeline);
|
|
192
|
+
return pipeline;
|
|
193
|
+
}
|
|
194
|
+
/** The rewritten pipeline for one stride: position from each of two buffers of that stride. */
|
|
195
|
+
dynamicPipelineFor(stride) {
|
|
196
|
+
const held = this.dynamicPipelines.get(stride);
|
|
197
|
+
if (held !== undefined)
|
|
198
|
+
return held;
|
|
199
|
+
const module = this.module;
|
|
200
|
+
const layout = this.pipelineLayout;
|
|
201
|
+
if (module === null || layout === null)
|
|
202
|
+
return null;
|
|
203
|
+
const pipeline = this.device.createRenderPipeline({
|
|
204
|
+
label: `recon.motion.dynamic.${String(stride)}`,
|
|
205
|
+
layout,
|
|
206
|
+
vertex: {
|
|
207
|
+
module,
|
|
208
|
+
entryPoint: 'motionDynamicVert',
|
|
209
|
+
buffers: [
|
|
210
|
+
{
|
|
211
|
+
arrayStride: stride,
|
|
212
|
+
attributes: [{ shaderLocation: 0, offset: 0, format: 'float32x3' }],
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
arrayStride: stride,
|
|
216
|
+
attributes: [{ shaderLocation: 1, offset: 0, format: 'float32x3' }],
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
},
|
|
220
|
+
fragment: { module, entryPoint: 'motionFrag', targets: [{ format: MOTION_TARGET_FORMAT }] },
|
|
221
|
+
primitive: { topology: 'triangle-list', cullMode: 'back' },
|
|
222
|
+
depthStencil: {
|
|
223
|
+
format: DEPTH_FORMAT,
|
|
224
|
+
depthWriteEnabled: false,
|
|
225
|
+
depthCompare: DEPTH_COMPARE_EQUAL,
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
this.dynamicPipelines.set(stride, pipeline);
|
|
229
|
+
return pipeline;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* The instanced pipeline for one mesh stride: the mesh's positions, then this frame's and last
|
|
233
|
+
* frame's placements, one matrix an instance, as the scene's instanced stage reads them.
|
|
234
|
+
*/
|
|
235
|
+
instancedPipelineFor(stride) {
|
|
236
|
+
const held = this.instancedPipelines.get(stride);
|
|
237
|
+
if (held !== undefined)
|
|
238
|
+
return held;
|
|
239
|
+
const module = this.module;
|
|
240
|
+
const layout = this.pipelineLayout;
|
|
241
|
+
if (module === null || layout === null)
|
|
242
|
+
return null;
|
|
243
|
+
const placement = (first) => ({
|
|
244
|
+
arrayStride: INSTANCE_STRIDE,
|
|
245
|
+
stepMode: 'instance',
|
|
246
|
+
attributes: [
|
|
247
|
+
{ shaderLocation: first, offset: 0, format: 'float32x4' },
|
|
248
|
+
{ shaderLocation: first + 1, offset: 16, format: 'float32x4' },
|
|
249
|
+
{ shaderLocation: first + 2, offset: 32, format: 'float32x4' },
|
|
250
|
+
{ shaderLocation: first + 3, offset: 48, format: 'float32x4' },
|
|
251
|
+
],
|
|
252
|
+
});
|
|
253
|
+
const pipeline = this.device.createRenderPipeline({
|
|
254
|
+
label: `recon.motion.instanced.${String(stride)}`,
|
|
255
|
+
layout,
|
|
256
|
+
vertex: {
|
|
257
|
+
module,
|
|
258
|
+
entryPoint: 'motionInstancedVert',
|
|
259
|
+
buffers: [
|
|
260
|
+
{
|
|
261
|
+
arrayStride: stride,
|
|
262
|
+
attributes: [{ shaderLocation: 0, offset: 0, format: 'float32x3' }],
|
|
263
|
+
},
|
|
264
|
+
placement(2),
|
|
265
|
+
placement(6),
|
|
266
|
+
],
|
|
267
|
+
},
|
|
268
|
+
fragment: { module, entryPoint: 'motionFrag', targets: [{ format: MOTION_TARGET_FORMAT }] },
|
|
269
|
+
primitive: { topology: 'triangle-list', cullMode: 'back' },
|
|
270
|
+
depthStencil: {
|
|
271
|
+
format: DEPTH_FORMAT,
|
|
272
|
+
depthWriteEnabled: false,
|
|
273
|
+
depthCompare: DEPTH_COMPARE_EQUAL,
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
this.instancedPipelines.set(stride, pipeline);
|
|
277
|
+
return pipeline;
|
|
278
|
+
}
|
|
279
|
+
/** The bind group holding one pair of palettes, built the first time the pair is seen. */
|
|
280
|
+
paletteGroup(now, was) {
|
|
281
|
+
const layout = this.paletteLayout;
|
|
282
|
+
if (layout === null)
|
|
283
|
+
return null;
|
|
284
|
+
let byWas = this.paletteGroups.get(now);
|
|
285
|
+
if (byWas === undefined) {
|
|
286
|
+
byWas = new Map();
|
|
287
|
+
this.paletteGroups.set(now, byWas);
|
|
288
|
+
}
|
|
289
|
+
let group = byWas.get(was);
|
|
290
|
+
if (group === undefined) {
|
|
291
|
+
group = this.device.createBindGroup({
|
|
292
|
+
label: 'recon.motion.palettes',
|
|
293
|
+
layout,
|
|
294
|
+
entries: [
|
|
295
|
+
{ binding: 0, resource: now },
|
|
296
|
+
{ binding: 1, resource: was },
|
|
297
|
+
],
|
|
298
|
+
});
|
|
299
|
+
byWas.set(was, group);
|
|
300
|
+
}
|
|
301
|
+
return group;
|
|
302
|
+
}
|
|
303
|
+
/** The pipeline for one vertex stride, built on first sight of it. */
|
|
304
|
+
pipelineFor(stride) {
|
|
305
|
+
const held = this.pipelines.get(stride);
|
|
306
|
+
if (held !== undefined)
|
|
307
|
+
return held;
|
|
308
|
+
const module = this.module;
|
|
309
|
+
const layout = this.pipelineLayout;
|
|
310
|
+
if (module === null || layout === null)
|
|
311
|
+
return null;
|
|
312
|
+
const pipeline = this.device.createRenderPipeline({
|
|
313
|
+
label: `recon.motion.${String(stride)}`,
|
|
314
|
+
layout,
|
|
315
|
+
vertex: {
|
|
316
|
+
module,
|
|
317
|
+
entryPoint: 'motionVert',
|
|
318
|
+
buffers: [
|
|
319
|
+
{
|
|
320
|
+
arrayStride: stride,
|
|
321
|
+
attributes: [{ shaderLocation: 0, offset: 0, format: 'float32x3' }],
|
|
322
|
+
},
|
|
323
|
+
],
|
|
324
|
+
},
|
|
325
|
+
fragment: { module, entryPoint: 'motionFrag', targets: [{ format: MOTION_TARGET_FORMAT }] },
|
|
326
|
+
/*
|
|
327
|
+
* **The scene's own winding**, because this draws the scene's geometry through the scene's
|
|
328
|
+
* clip transform — the product the renderer hands over already carries the negation that
|
|
329
|
+
* `naga` writes into every generated vertex stage, so the faces come out the way they did
|
|
330
|
+
* and a `cw` front face here would draw the inside of every mesh. §3 row 57.
|
|
331
|
+
*/
|
|
332
|
+
primitive: { topology: 'triangle-list', cullMode: 'back' },
|
|
333
|
+
depthStencil: {
|
|
334
|
+
format: DEPTH_FORMAT,
|
|
335
|
+
/*
|
|
336
|
+
* **Tested and not written.** The frame's depth is finished; this pass only wants the
|
|
337
|
+
* pixels the scene actually kept, and `DEPTH_COMPARE_EQUAL` is the comparison that admits
|
|
338
|
+
* exactly them — the same transform on the same positions gives the same depth, which is
|
|
339
|
+
* why the rasterisation matrix is handed over whole rather than rebuilt here.
|
|
340
|
+
*
|
|
341
|
+
* **And the equality is not fragile here**, which was worth measuring rather than
|
|
342
|
+
* assuming: this driver contracts multiply-adds (§3 row 107) and two shader modules can
|
|
343
|
+
* contract a matrix product differently, so an equality across them could have admitted
|
|
344
|
+
* only some of a surface. Run with `greater-equal` instead, the ghost measured the same
|
|
345
|
+
* to the pixel — 5,942 either way — so nothing is being dropped.
|
|
346
|
+
*/
|
|
347
|
+
depthWriteEnabled: false,
|
|
348
|
+
depthCompare: DEPTH_COMPARE_EQUAL,
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
this.pipelines.set(stride, pipeline);
|
|
352
|
+
return pipeline;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Every mover of the frame, into `target`, tested against the finished `depth`.
|
|
356
|
+
*
|
|
357
|
+
* **After everything that draws and before the resolve reads it.** `raster` is the scene's clip
|
|
358
|
+
* transform with the generated stages' y negation folded in; `viewProj` and `previousViewProj`
|
|
359
|
+
* are this frame's and last frame's unjittered view-projections.
|
|
360
|
+
*
|
|
361
|
+
* **Cleared every frame, even when nothing moved.** A texel left from last frame is a flag saying
|
|
362
|
+
* "a draw wrote this", and the resolve would take a motion belonging to a surface that is no
|
|
363
|
+
* longer there. The clear is the pass's own load operation, so an empty frame still runs it.
|
|
364
|
+
*/
|
|
365
|
+
run(encoder, target, depth, raster, viewProj, previousViewProj, timestampWrites) {
|
|
366
|
+
this.buildLayout();
|
|
367
|
+
const layout = this.layout;
|
|
368
|
+
if (layout === null)
|
|
369
|
+
return;
|
|
370
|
+
const pass = encoder.beginRenderPass({
|
|
371
|
+
label: 'recon.motion',
|
|
372
|
+
timestampWrites,
|
|
373
|
+
colorAttachments: [
|
|
374
|
+
{ view: target, loadOp: 'clear', storeOp: 'store', clearValue: [0, 0, 0, 0] },
|
|
375
|
+
],
|
|
376
|
+
depthStencilAttachment: {
|
|
377
|
+
view: depth,
|
|
378
|
+
depthLoadOp: 'load',
|
|
379
|
+
depthStoreOp: 'store',
|
|
380
|
+
depthReadOnly: false,
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
const count = this.count;
|
|
384
|
+
if (count > 0) {
|
|
385
|
+
const bytes = count * MOTION_DRAW_STRIDE;
|
|
386
|
+
if (this.drawCapacity < count) {
|
|
387
|
+
this.drawBuffer?.destroy();
|
|
388
|
+
this.drawCapacity = Math.max(count, this.drawCapacity * 2, 16);
|
|
389
|
+
this.drawBuffer = this.device.createBuffer({
|
|
390
|
+
label: 'recon.motion.draws',
|
|
391
|
+
size: this.drawCapacity * MOTION_DRAW_STRIDE,
|
|
392
|
+
usage: 0x40 | 0x8, // UNIFORM | COPY_DST
|
|
393
|
+
});
|
|
394
|
+
this.drawStaging = new Uint8Array(this.drawCapacity * MOTION_DRAW_STRIDE);
|
|
395
|
+
this.drawFloats = new Float32Array(this.drawStaging.buffer);
|
|
396
|
+
this.group = null;
|
|
397
|
+
}
|
|
398
|
+
this.frameBuffer ??= this.device.createBuffer({
|
|
399
|
+
label: 'recon.motion.frame',
|
|
400
|
+
size: MOTION_FRAME_FLOATS * 4,
|
|
401
|
+
usage: 0x40 | 0x8,
|
|
402
|
+
});
|
|
403
|
+
this.group ??= this.device.createBindGroup({
|
|
404
|
+
label: 'recon.motion.group',
|
|
405
|
+
layout,
|
|
406
|
+
entries: [
|
|
407
|
+
{ binding: 0, resource: { buffer: this.frameBuffer } },
|
|
408
|
+
{
|
|
409
|
+
binding: 1,
|
|
410
|
+
resource: { buffer: this.drawBuffer, size: MOTION_DRAW_STRIDE },
|
|
411
|
+
},
|
|
412
|
+
],
|
|
413
|
+
});
|
|
414
|
+
this.frameStaging.set(raster, 0);
|
|
415
|
+
this.frameStaging.set(viewProj, 16);
|
|
416
|
+
this.frameStaging.set(previousViewProj, 32);
|
|
417
|
+
this.device.queue.writeBuffer(this.frameBuffer, 0, this.frameStaging);
|
|
418
|
+
/* Copied a float at a time rather than through `subarray`, which is a view allocated per
|
|
419
|
+
mover per frame. */
|
|
420
|
+
for (let i = 0; i < count; i += 1) {
|
|
421
|
+
const from = i * MOTION_DRAW_FLOATS;
|
|
422
|
+
const to = (i * MOTION_DRAW_STRIDE) / 4;
|
|
423
|
+
for (let k = 0; k < MOTION_DRAW_FLOATS; k += 1) {
|
|
424
|
+
this.drawFloats[to + k] = this.matrices[from + k];
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
this.device.queue.writeBuffer(this.drawBuffer, 0, this.drawStaging, 0, bytes);
|
|
428
|
+
let bound = null;
|
|
429
|
+
for (let i = 0; i < count; i += 1) {
|
|
430
|
+
const mesh = this.meshes[i];
|
|
431
|
+
if (mesh === undefined)
|
|
432
|
+
continue;
|
|
433
|
+
const kind = this.kinds[i];
|
|
434
|
+
let pipeline = null;
|
|
435
|
+
let instances = 1;
|
|
436
|
+
if (kind === INSTANCED) {
|
|
437
|
+
const now = this.instancesNow[i] ?? null;
|
|
438
|
+
const was = this.instancesWas[i] ?? null;
|
|
439
|
+
if (now === null || was === null)
|
|
440
|
+
continue;
|
|
441
|
+
pipeline = this.instancedPipelineFor(mesh.vertexStride);
|
|
442
|
+
pass.setVertexBuffer(1, now);
|
|
443
|
+
pass.setVertexBuffer(2, was);
|
|
444
|
+
instances = this.instanceCounts[i] ?? 0;
|
|
445
|
+
}
|
|
446
|
+
else if (kind === DYNAMIC) {
|
|
447
|
+
const previous = this.previousRows[i] ?? null;
|
|
448
|
+
if (previous === null)
|
|
449
|
+
continue;
|
|
450
|
+
pipeline = this.dynamicPipelineFor(mesh.vertexStride);
|
|
451
|
+
pass.setVertexBuffer(1, previous);
|
|
452
|
+
}
|
|
453
|
+
else if (kind === SKINNED) {
|
|
454
|
+
const offsets = mesh.skinOffsets;
|
|
455
|
+
const now = this.paletteNow[i] ?? null;
|
|
456
|
+
const was = this.paletteWas[i] ?? null;
|
|
457
|
+
if (offsets === null || now === null || was === null)
|
|
458
|
+
continue;
|
|
459
|
+
pipeline = this.skinnedPipelineFor(mesh.vertexStride, offsets);
|
|
460
|
+
const palettes = this.paletteGroup(now, was);
|
|
461
|
+
if (pipeline === null || palettes === null)
|
|
462
|
+
continue;
|
|
463
|
+
pass.setBindGroup(1, palettes);
|
|
464
|
+
}
|
|
465
|
+
else {
|
|
466
|
+
pipeline = this.pipelineFor(mesh.vertexStride);
|
|
467
|
+
}
|
|
468
|
+
if (pipeline === null)
|
|
469
|
+
continue;
|
|
470
|
+
if (pipeline !== bound) {
|
|
471
|
+
pass.setPipeline(pipeline);
|
|
472
|
+
bound = pipeline;
|
|
473
|
+
}
|
|
474
|
+
pass.setBindGroup(0, this.group, [i * MOTION_DRAW_STRIDE]);
|
|
475
|
+
pass.setVertexBuffer(0, mesh.vertexBuffers[0]);
|
|
476
|
+
pass.setIndexBuffer(mesh.indexBuffer, 'uint32');
|
|
477
|
+
pass.drawIndexed(mesh.indexCount, instances);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
pass.end();
|
|
481
|
+
}
|
|
482
|
+
dispose() {
|
|
483
|
+
this.paletteGroups.clear();
|
|
484
|
+
this.frameBuffer?.destroy();
|
|
485
|
+
this.drawBuffer?.destroy();
|
|
486
|
+
this.frameBuffer = null;
|
|
487
|
+
this.drawBuffer = null;
|
|
488
|
+
this.drawCapacity = 0;
|
|
489
|
+
this.group = null;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
@@ -32,6 +32,15 @@ export declare class PipelineCache {
|
|
|
32
32
|
* by every `describe` callback.
|
|
33
33
|
*/
|
|
34
34
|
readonly sampleCount: number;
|
|
35
|
+
/**
|
|
36
|
+
* Whether the lit pipelines here read glass in their shadows: `glassShadows` other than `'off'`.
|
|
37
|
+
*
|
|
38
|
+
* **Carried by the cache for the reason the format is**: one value every lit pipeline is built
|
|
39
|
+
* with, chosen once by the renderer. It is the `GLASS_SHADOWS` override the generated lit shader
|
|
40
|
+
* branches on (see `FlatShaderOptions.glassShadows`), so off specialises the lookups away rather
|
|
41
|
+
* than leaving code that returns at its first line and still costs the pass its registers.
|
|
42
|
+
*/
|
|
43
|
+
readonly glassShadows: boolean;
|
|
35
44
|
private readonly device;
|
|
36
45
|
private readonly pipelines;
|
|
37
46
|
/**
|
|
@@ -49,7 +58,7 @@ export declare class PipelineCache {
|
|
|
49
58
|
* wait for readiness rather than discovering it mid-frame.
|
|
50
59
|
*/
|
|
51
60
|
private readonly compiling;
|
|
52
|
-
constructor(device: GPUDevice, format: GPUTextureFormat, sampleCount?: number);
|
|
61
|
+
constructor(device: GPUDevice, format: GPUTextureFormat, sampleCount?: number, glassShadows?: boolean);
|
|
53
62
|
/** How many distinct pipelines have been built. Read by tests and diagnostics. */
|
|
54
63
|
get size(): number;
|
|
55
64
|
/**
|
|
@@ -32,6 +32,15 @@ export class PipelineCache {
|
|
|
32
32
|
* by every `describe` callback.
|
|
33
33
|
*/
|
|
34
34
|
sampleCount;
|
|
35
|
+
/**
|
|
36
|
+
* Whether the lit pipelines here read glass in their shadows: `glassShadows` other than `'off'`.
|
|
37
|
+
*
|
|
38
|
+
* **Carried by the cache for the reason the format is**: one value every lit pipeline is built
|
|
39
|
+
* with, chosen once by the renderer. It is the `GLASS_SHADOWS` override the generated lit shader
|
|
40
|
+
* branches on (see `FlatShaderOptions.glassShadows`), so off specialises the lookups away rather
|
|
41
|
+
* than leaving code that returns at its first line and still costs the pass its registers.
|
|
42
|
+
*/
|
|
43
|
+
glassShadows;
|
|
35
44
|
device;
|
|
36
45
|
pipelines = new Map();
|
|
37
46
|
/**
|
|
@@ -49,10 +58,11 @@ export class PipelineCache {
|
|
|
49
58
|
* wait for readiness rather than discovering it mid-frame.
|
|
50
59
|
*/
|
|
51
60
|
compiling = new Map();
|
|
52
|
-
constructor(device, format, sampleCount = 1) {
|
|
61
|
+
constructor(device, format, sampleCount = 1, glassShadows = true) {
|
|
53
62
|
this.device = device;
|
|
54
63
|
this.format = format;
|
|
55
64
|
this.sampleCount = sampleCount;
|
|
65
|
+
this.glassShadows = glassShadows;
|
|
56
66
|
}
|
|
57
67
|
/** How many distinct pipelines have been built. Read by tests and diagnostics. */
|
|
58
68
|
get size() {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { MipPipelines } from './surfaceTexturePass.ts';
|
|
2
|
+
export declare class GpuPointGlassTint {
|
|
3
|
+
readonly texture: GPUTexture;
|
|
4
|
+
/** The whole array, for the lit pass. */
|
|
5
|
+
readonly view: GPUTextureView;
|
|
6
|
+
/** The colour scratch a face's glass is multiplied into. */
|
|
7
|
+
readonly scratchView: GPUTextureView;
|
|
8
|
+
readonly edge: number;
|
|
9
|
+
private readonly device;
|
|
10
|
+
private readonly pipelines;
|
|
11
|
+
private readonly scratch;
|
|
12
|
+
private readonly layerViews;
|
|
13
|
+
private readonly mips;
|
|
14
|
+
private readonly pipeline;
|
|
15
|
+
private readonly bindGroup;
|
|
16
|
+
private readonly ring;
|
|
17
|
+
private readonly heldFaces;
|
|
18
|
+
private readonly dirty;
|
|
19
|
+
constructor(device: GPUDevice, pipelines: MipPipelines, faceSize: number, edge: number, layers: number,
|
|
20
|
+
/** Resolves a frame can make: the array's own figure, since every face resolves once. */
|
|
21
|
+
slots: number, encoder: GPUCommandEncoder);
|
|
22
|
+
/** Whether `face` of `layer` holds glass: a face that does must be cleared before it is reused. */
|
|
23
|
+
held(layer: number, face: number): boolean;
|
|
24
|
+
/** Copy the colour scratch into `face`'s region of `layer`, and remember whether it held glass. */
|
|
25
|
+
resolve(encoder: GPUCommandEncoder, layer: number, face: number, drawn: boolean): void;
|
|
26
|
+
/** The chain frost reads, for every layer touched since the last call. */
|
|
27
|
+
recordMips(encoder: GPUCommandEncoder): void;
|
|
28
|
+
beginFrame(): void;
|
|
29
|
+
/** Before the round's submit: the slots are written and must be up before any pass reads. */
|
|
30
|
+
flush(): void;
|
|
31
|
+
dispose(): void;
|
|
32
|
+
}
|