@driftengine/core 4.9.0 → 4.11.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 +133 -11
- package/README.md +43 -38
- package/dist/index.d.ts +7 -4
- package/dist/index.js +5 -4
- package/dist/render/ambientHarmonics.d.ts +1 -1
- package/dist/render/ambientHarmonics.js +1 -1
- package/dist/render/areaLights.d.ts +4 -4
- package/dist/render/areaLights.js +1 -1
- package/dist/render/backend/api.d.ts +10 -3
- package/dist/render/backend/select.js +11 -5
- package/dist/render/backend/webgl2/boneAnimations.d.ts +29 -0
- package/dist/render/backend/webgl2/boneAnimations.js +80 -0
- package/dist/render/backend/webgl2/instanced.d.ts +5 -1
- package/dist/render/backend/webgl2/instanced.js +13 -1
- package/dist/render/backend/webgl2/renderer.d.ts +189 -4
- package/dist/render/backend/webgl2/renderer.js +614 -66
- package/dist/render/backend/webgl2/skinPaletteTexture.d.ts +5 -3
- package/dist/render/backend/webgl2/skinPaletteTexture.js +6 -4
- package/dist/render/backend/webgpu/boneAnimations.d.ts +34 -0
- package/dist/render/backend/webgpu/boneAnimations.js +76 -0
- package/dist/render/backend/webgpu/buffers.d.ts +24 -4
- package/dist/render/backend/webgpu/buffers.js +116 -59
- package/dist/render/backend/webgpu/clothKernels.d.ts +8 -0
- package/dist/render/backend/webgpu/clothKernels.js +76 -0
- package/dist/render/backend/webgpu/clothOps.d.ts +39 -0
- package/dist/render/backend/webgpu/clothOps.js +78 -0
- package/dist/render/backend/webgpu/clothSetLayout.d.ts +25 -0
- package/dist/render/backend/webgpu/clothSetLayout.js +84 -0
- package/dist/render/backend/webgpu/clothSetPack.d.ts +33 -0
- package/dist/render/backend/webgpu/clothSetPack.js +144 -0
- package/dist/render/backend/webgpu/compressedUpload.d.ts +0 -1
- package/dist/render/backend/webgpu/compressedUpload.js +53 -8
- package/dist/render/backend/webgpu/depthPass.d.ts +59 -3
- package/dist/render/backend/webgpu/depthPass.js +49 -14
- package/dist/render/backend/webgpu/drawCommand.d.ts +20 -4
- package/dist/render/backend/webgpu/drawCommand.js +11 -3
- package/dist/render/backend/webgpu/flatPass.d.ts +85 -42
- package/dist/render/backend/webgpu/flatPass.js +137 -20
- package/dist/render/backend/webgpu/gpuClothSet.d.ts +80 -0
- package/dist/render/backend/webgpu/gpuClothSet.js +462 -0
- package/dist/render/backend/webgpu/instanced.d.ts +14 -1
- package/dist/render/backend/webgpu/instanced.js +24 -1
- package/dist/render/backend/webgpu/latePass.js +1 -0
- package/dist/render/backend/webgpu/materialStore.d.ts +101 -0
- package/dist/render/backend/webgpu/materialStore.js +265 -0
- package/dist/render/backend/webgpu/motionPass.js +15 -6
- package/dist/render/backend/webgpu/pipelineCache.d.ts +28 -1
- package/dist/render/backend/webgpu/pipelineCache.js +46 -1
- package/dist/render/backend/webgpu/postPass.d.ts +1 -1
- package/dist/render/backend/webgpu/renderer.d.ts +200 -35
- package/dist/render/backend/webgpu/renderer.js +993 -168
- package/dist/render/backend/webgpu/shaders/clothSolve.wgsl.d.ts +9 -2
- package/dist/render/backend/webgpu/shaders/clothSolve.wgsl.js +121 -47
- package/dist/render/backend/webgpu/skinPaletteRing.d.ts +7 -3
- package/dist/render/backend/webgpu/skinPaletteRing.js +13 -7
- package/dist/render/backend/webgpu/skinPaletteTexture.d.ts +6 -0
- package/dist/render/backend/webgpu/skinPaletteTexture.js +7 -1
- package/dist/render/backend/webgpu/staticBundles.d.ts +125 -0
- package/dist/render/backend/webgpu/staticBundles.js +242 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +10 -3
- package/dist/render/backend/webgpu/surfaceTexturePass.js +20 -2
- package/dist/render/backend/webgpu/uniformRing.d.ts +21 -0
- package/dist/render/backend/webgpu/uniformRing.js +9 -1
- package/dist/render/backend/webgpu/vertexFormats.d.ts +22 -0
- package/dist/render/backend/webgpu/vertexFormats.js +97 -0
- package/dist/render/bloomChain.d.ts +3 -3
- package/dist/render/boneAnimation.d.ts +92 -0
- package/dist/render/boneAnimation.js +133 -0
- package/dist/render/compressedSource.d.ts +33 -13
- package/dist/render/compressedSource.js +70 -25
- package/dist/render/glCompressed.js +83 -0
- package/dist/render/globalMediumPass.d.ts +2 -0
- package/dist/render/globalMediumPass.js +1 -0
- package/dist/render/indexWidth.d.ts +17 -0
- package/dist/render/indexWidth.js +23 -0
- package/dist/render/instances.d.ts +26 -0
- package/dist/render/lightBudget.d.ts +10 -0
- package/dist/render/lightBudget.js +10 -0
- package/dist/render/lightMatrix.d.ts +11 -0
- package/dist/render/lightMatrix.js +14 -0
- package/dist/render/lightmap.d.ts +1 -1
- package/dist/render/mesh.d.ts +14 -0
- package/dist/render/mesh.js +44 -14
- package/dist/render/pointLightSelection.d.ts +4 -4
- package/dist/render/renderQuality.d.ts +30 -0
- package/dist/render/renderQuality.js +5 -0
- package/dist/render/rendererHarness.d.ts +7 -0
- package/dist/render/rendererHarness.js +12 -0
- package/dist/render/screenSpaceReflection.d.ts +2 -1
- package/dist/render/shader.d.ts +15 -0
- package/dist/render/shader.js +41 -0
- package/dist/render/shaders/boneAnimation.d.ts +19 -0
- package/dist/render/shaders/boneAnimation.js +63 -0
- package/dist/render/shaders/depth.d.ts +7 -0
- package/dist/render/shaders/depth.js +35 -10
- package/dist/render/shaders/flat/directionalShadow.js +84 -10
- package/dist/render/shaders/flat/glassTint.d.ts +1 -1
- package/dist/render/shaders/flat/glassTint.js +3 -0
- package/dist/render/shaders/flat/index.d.ts +21 -0
- package/dist/render/shaders/flat/index.js +42 -7
- package/dist/render/shaders/flat/layered.d.ts +19 -0
- package/dist/render/shaders/flat/layered.js +115 -0
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +58 -21
- package/dist/render/shaders/flat/mapReads.d.ts +10 -0
- package/dist/render/shaders/flat/mapReads.js +38 -0
- package/dist/render/shaders/flat/models.js +1 -1
- package/dist/render/shaders/flat/movingSun.d.ts +21 -0
- package/dist/render/shaders/flat/movingSun.js +46 -0
- package/dist/render/shaders/flat/normalMap.d.ts +6 -2
- package/dist/render/shaders/flat/normalMap.js +14 -3
- package/dist/render/shaders/flat/overlay.d.ts +3 -2
- package/dist/render/shaders/flat/overlay.js +42 -20
- package/dist/render/shaders/flat/pointShadow.js +2 -2
- package/dist/render/shaders/flat/preamble.js +59 -27
- package/dist/render/shaders/flat/worldUv.d.ts +22 -0
- package/dist/render/shaders/flat/worldUv.js +113 -0
- package/dist/render/shaders/generated/depth.wgsl.d.ts +93 -0
- package/dist/render/shaders/generated/depth.wgsl.js +93 -0
- package/dist/render/shaders/generated/flat.wgsl.d.ts +3616 -3042
- package/dist/render/shaders/generated/flat.wgsl.js +3688 -3113
- package/dist/render/shaders/generated/globalMedium.wgsl.d.ts +8 -3
- package/dist/render/shaders/generated/globalMedium.wgsl.js +8 -3
- package/dist/render/shaders/generated/lightVolume.wgsl.d.ts +15 -10
- package/dist/render/shaders/generated/lightVolume.wgsl.js +16 -11
- package/dist/render/shaders/globalMedium.js +9 -1
- package/dist/render/shaders/lightVolume.js +9 -1
- package/dist/render/shaders/outputTransform.d.ts +7 -0
- package/dist/render/shaders/outputTransform.js +28 -14
- package/dist/render/shaders/tangentFrame.d.ts +1 -1
- package/dist/render/shaders/tangentFrame.js +16 -3
- package/dist/render/shaders/vertexChannel.d.ts +7 -0
- package/dist/render/shaders/vertexChannel.js +26 -0
- package/dist/render/skinnedClothRun.d.ts +28 -0
- package/dist/render/skinnedClothRun.js +103 -35
- package/dist/render/staticDraws.d.ts +47 -0
- package/dist/render/staticDraws.js +43 -0
- package/dist/render/surfaceLayers.d.ts +39 -0
- package/dist/render/surfaceLayers.js +26 -0
- package/dist/render/surfaceOverlay.d.ts +16 -3
- package/dist/render/surfaceOverlay.js +11 -6
- package/dist/render/surfaceProjection.d.ts +34 -0
- package/dist/render/surfaceProjection.js +30 -0
- package/dist/render/surfaceTexture.d.ts +68 -7
- package/dist/render/surfaceTexture.js +56 -17
- package/dist/render/vertexPacking.d.ts +48 -0
- package/dist/render/vertexPacking.js +68 -0
- package/package.json +6 -6
- package/src/index.ts +12 -4
- package/src/render/ambientHarmonics.ts +1 -1
- package/src/render/areaLights.ts +4 -4
- package/src/render/backend/api.ts +13 -3
- package/src/render/backend/select.ts +10 -5
- package/src/render/backend/webgl2/boneAnimations.ts +105 -0
- package/src/render/backend/webgl2/instanced.ts +20 -1
- package/src/render/backend/webgl2/renderer.ts +723 -79
- package/src/render/backend/webgl2/skinPaletteTexture.ts +6 -4
- package/src/render/backend/webgpu/boneAnimations.ts +97 -0
- package/src/render/backend/webgpu/buffers.ts +195 -70
- package/src/render/backend/webgpu/clothKernels.ts +86 -0
- package/src/render/backend/webgpu/clothOps.ts +86 -0
- package/src/render/backend/webgpu/clothSetLayout.ts +102 -0
- package/src/render/backend/webgpu/clothSetPack.ts +197 -0
- package/src/render/backend/webgpu/compressedUpload.ts +59 -9
- package/src/render/backend/webgpu/depthPass.ts +51 -10
- package/src/render/backend/webgpu/drawCommand.ts +25 -4
- package/src/render/backend/webgpu/flatPass.ts +212 -41
- package/src/render/backend/webgpu/gpuClothSet.ts +564 -0
- package/src/render/backend/webgpu/instanced.ts +32 -1
- package/src/render/backend/webgpu/latePass.ts +1 -0
- package/src/render/backend/webgpu/materialStore.ts +276 -0
- package/src/render/backend/webgpu/motionPass.ts +18 -7
- package/src/render/backend/webgpu/pipelineCache.ts +53 -7
- package/src/render/backend/webgpu/renderer.ts +1201 -202
- package/src/render/backend/webgpu/shaders/clothSolve.wgsl.ts +121 -47
- package/src/render/backend/webgpu/skinPaletteRing.ts +13 -7
- package/src/render/backend/webgpu/skinPaletteTexture.ts +7 -1
- package/src/render/backend/webgpu/staticBundles.ts +364 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +29 -3
- package/src/render/backend/webgpu/uniformRing.ts +10 -1
- package/src/render/backend/webgpu/vertexFormats.ts +113 -0
- package/src/render/bloomChain.ts +3 -3
- package/src/render/boneAnimation.ts +223 -0
- package/src/render/compressedSource.ts +121 -29
- package/src/render/glCompressed.ts +83 -0
- package/src/render/globalMediumPass.ts +7 -0
- package/src/render/indexWidth.ts +27 -0
- package/src/render/instances.ts +27 -0
- package/src/render/lightBudget.ts +11 -0
- package/src/render/lightMatrix.ts +15 -0
- package/src/render/lightmap.ts +1 -1
- package/src/render/mesh.ts +72 -14
- package/src/render/pointLightSelection.ts +4 -4
- package/src/render/renderQuality.ts +38 -0
- package/src/render/rendererHarness.ts +15 -0
- package/src/render/screenSpaceReflection.ts +2 -1
- package/src/render/shader.ts +59 -0
- package/src/render/shaders/boneAnimation.ts +63 -0
- package/src/render/shaders/depth.ts +45 -10
- package/src/render/shaders/flat/directionalShadow.ts +84 -10
- package/src/render/shaders/flat/glassTint.ts +7 -1
- package/src/render/shaders/flat/index.ts +63 -7
- package/src/render/shaders/flat/layered.ts +115 -0
- package/src/render/shaders/flat/main.ts +58 -21
- package/src/render/shaders/flat/mapReads.ts +38 -0
- package/src/render/shaders/flat/models.ts +1 -1
- package/src/render/shaders/flat/movingSun.ts +46 -0
- package/src/render/shaders/flat/normalMap.ts +14 -3
- package/src/render/shaders/flat/overlay.ts +42 -20
- package/src/render/shaders/flat/pointShadow.ts +2 -2
- package/src/render/shaders/flat/preamble.ts +59 -27
- package/src/render/shaders/flat/worldUv.ts +113 -0
- package/src/render/shaders/generated/depth.wgsl.ts +95 -0
- package/src/render/shaders/generated/flat.wgsl.ts +3688 -3113
- package/src/render/shaders/generated/globalMedium.wgsl.ts +8 -3
- package/src/render/shaders/generated/lightVolume.wgsl.ts +16 -11
- package/src/render/shaders/globalMedium.ts +9 -1
- package/src/render/shaders/lightVolume.ts +9 -1
- package/src/render/shaders/outputTransform.ts +30 -14
- package/src/render/shaders/tangentFrame.ts +16 -3
- package/src/render/shaders/vertexChannel.ts +27 -0
- package/src/render/skinnedClothRun.ts +138 -38
- package/src/render/staticDraws.ts +95 -0
- package/src/render/surfaceLayers.ts +57 -0
- package/src/render/surfaceOverlay.ts +24 -7
- package/src/render/surfaceProjection.ts +57 -0
- package/src/render/surfaceTexture.ts +124 -27
- package/src/render/vertexPacking.ts +109 -0
- package/dist/render/backend/webgpu/gpuSkinnedCloth.d.ts +0 -74
- package/dist/render/backend/webgpu/gpuSkinnedCloth.js +0 -452
- package/src/render/backend/webgpu/gpuSkinnedCloth.ts +0 -502
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* each kernel there is an entry point here, one invocation a particle or a constraint, and the loop
|
|
8
8
|
* over a batch is the dispatch. `clothPose.ts`' `skinParticles` is `pose`. The order of a step —
|
|
9
9
|
* begin, then per substep predict, the batches, the limits, finish; then the blend — is
|
|
10
|
-
* `
|
|
10
|
+
* `gpuClothSet.ts`', taken from the same `ClothControl` the CPU solver is driven by.
|
|
11
11
|
*
|
|
12
12
|
* **Where it differs, it says so.** Single precision throughout, where the CPU rounds to single
|
|
13
13
|
* only on a store. And the bending angle is `atan2(|n1 × n2|, n1 · n2)` rather than `acos(n1 · n2)`
|
|
@@ -28,33 +28,44 @@
|
|
|
28
28
|
* start; `pose` the two skinned poses a step interpolates between and the latest skinned normals;
|
|
29
29
|
* `statics` everything per particle that never changes. A section's offset is a multiple of the
|
|
30
30
|
* particle count, which the constants carry — so no offset is a uniform to keep in step.
|
|
31
|
+
*
|
|
32
|
+
* **One dispatch serves every garment of a set** (`clothSetPack.ts`): the particles, constraints,
|
|
33
|
+
* joints and colliders of all of them in those buffers, and each garment's numbers — its step's
|
|
34
|
+
* fraction and blend, its damping, gravity and limits — a record of its own in `paces`, at the
|
|
35
|
+
* round's place. A kernel finds its garment from the particle, and returns at once where that
|
|
36
|
+
* garment has nothing to do this round: a garment that took fewer steps, or one settling alone after
|
|
37
|
+
* a reset, sits the round out while the rest of the set runs it.
|
|
31
38
|
*/
|
|
32
39
|
export const CLOTH_WORKGROUP = 64;
|
|
33
40
|
|
|
34
41
|
export const CLOTH_SOLVE_WGSL = /* wgsl */ `
|
|
42
|
+
/* The set's: every garment's particles, records, skin matrices and colliders, and the step length
|
|
43
|
+
they all share. */
|
|
35
44
|
struct Constants {
|
|
36
45
|
count: u32,
|
|
37
46
|
distances: u32,
|
|
38
47
|
bendings: u32,
|
|
39
48
|
joints: u32,
|
|
40
49
|
colliders: u32,
|
|
41
|
-
/* 1 a max distance, 2 a backstop, 4 a frontstop: which limits the set-up has at all. */
|
|
42
|
-
limits: u32,
|
|
43
|
-
width: u32,
|
|
44
50
|
pad0: u32,
|
|
51
|
+
pad1: u32,
|
|
52
|
+
pad2: u32,
|
|
45
53
|
h: f32,
|
|
46
54
|
invH: f32,
|
|
47
55
|
invH2: f32,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
pad3: f32,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* Where this dispatch's round of records starts in paces, at a dynamic offset. */
|
|
60
|
+
struct Round {
|
|
61
|
+
at: u32,
|
|
62
|
+
pad0: u32,
|
|
63
|
+
pad1: u32,
|
|
64
|
+
pad2: u32,
|
|
54
65
|
}
|
|
55
66
|
|
|
56
|
-
/* One
|
|
57
|
-
struct
|
|
67
|
+
/* One garment's numbers for one round: its step's, and its own that never change. */
|
|
68
|
+
struct Pace {
|
|
58
69
|
fraction: f32,
|
|
59
70
|
blend: f32,
|
|
60
71
|
alpha: f32,
|
|
@@ -62,8 +73,10 @@ struct Step {
|
|
|
62
73
|
/* Where the pose a step starts from and the one it moves toward sit in pose, in floats. */
|
|
63
74
|
fromAt: u32,
|
|
64
75
|
toAt: u32,
|
|
65
|
-
|
|
66
|
-
|
|
76
|
+
/* 0 where the garment sits this round out. Not active, which WGSL reserves. */
|
|
77
|
+
live: u32,
|
|
78
|
+
/* 1 a max distance, 2 a backstop, 4 a frontstop: which limits the garment has at all. */
|
|
79
|
+
limits: u32,
|
|
67
80
|
/* The character's turn since the last step, by columns; origin.w is the share carried. */
|
|
68
81
|
turn0: vec4<f32>,
|
|
69
82
|
turn1: vec4<f32>,
|
|
@@ -72,9 +85,19 @@ struct Step {
|
|
|
72
85
|
shift: vec4<f32>,
|
|
73
86
|
/* The frame's wind: one wind, sampled once a frame, so a step's rather than the set-up's. */
|
|
74
87
|
wind: vec4<f32>,
|
|
88
|
+
colliderBase: u32,
|
|
89
|
+
colliders: u32,
|
|
90
|
+
width: u32,
|
|
91
|
+
pad0: u32,
|
|
92
|
+
keep: f32,
|
|
93
|
+
dragKeep: f32,
|
|
94
|
+
maxDistanceScale: f32,
|
|
95
|
+
margin: f32,
|
|
96
|
+
gravity: vec4<f32>,
|
|
75
97
|
}
|
|
76
98
|
|
|
77
|
-
/* One
|
|
99
|
+
/* One colour of one kind of constraint across the set, at a dynamic offset; first resets the
|
|
100
|
+
multipliers. Publishing reads one garment's particles as begin to end, and first is the garment. */
|
|
78
101
|
struct Batch {
|
|
79
102
|
begin: u32,
|
|
80
103
|
end: u32,
|
|
@@ -83,7 +106,7 @@ struct Batch {
|
|
|
83
106
|
}
|
|
84
107
|
|
|
85
108
|
@group(0) @binding(0) var<uniform> c: Constants;
|
|
86
|
-
@group(0) @binding(1) var<uniform>
|
|
109
|
+
@group(0) @binding(1) var<uniform> round: Round;
|
|
87
110
|
@group(0) @binding(2) var<uniform> batch: Batch;
|
|
88
111
|
@group(0) @binding(3) var<storage, read_write> state: array<f32>;
|
|
89
112
|
@group(0) @binding(4) var<storage, read_write> pose: array<f32>;
|
|
@@ -91,6 +114,12 @@ struct Batch {
|
|
|
91
114
|
@group(0) @binding(6) var<storage, read> constraints: array<u32>;
|
|
92
115
|
@group(0) @binding(7) var<storage, read_write> lambda: array<f32>;
|
|
93
116
|
@group(0) @binding(8) var<storage, read> frame: array<f32>;
|
|
117
|
+
@group(0) @binding(9) var<storage, read> paces: array<Pace>;
|
|
118
|
+
|
|
119
|
+
/* The record of particle i's garment this round: which garment a particle is, in statics. */
|
|
120
|
+
fn paceAt(i: u32) -> u32 {
|
|
121
|
+
return round.at + u32(statics[29u * c.count + i]);
|
|
122
|
+
}
|
|
94
123
|
|
|
95
124
|
fn stateAt(section: u32, i: u32) -> u32 {
|
|
96
125
|
return section * 3u * c.count + i * 3u;
|
|
@@ -121,10 +150,10 @@ fn inverseMass(i: u32) -> f32 {
|
|
|
121
150
|
}
|
|
122
151
|
|
|
123
152
|
/* Where skinning puts particle i, fraction of the way from the last pose to the latest. */
|
|
124
|
-
fn skinnedAt(i: u32) -> vec3<f32> {
|
|
125
|
-
let a = poseOf(
|
|
126
|
-
let b = poseOf(
|
|
127
|
-
return a + (b - a) *
|
|
153
|
+
fn skinnedAt(i: u32, g: u32) -> vec3<f32> {
|
|
154
|
+
let a = poseOf(paces[g].fromAt + i * 3u);
|
|
155
|
+
let b = poseOf(paces[g].toAt + i * 3u);
|
|
156
|
+
return a + (b - a) * paces[g].fraction;
|
|
128
157
|
}
|
|
129
158
|
|
|
130
159
|
fn skinMatrix(j: u32) -> mat4x4<f32> {
|
|
@@ -143,6 +172,10 @@ fn clothPose(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
|
143
172
|
if (i >= c.count) {
|
|
144
173
|
return;
|
|
145
174
|
}
|
|
175
|
+
let g = paceAt(i);
|
|
176
|
+
if (paces[g].live == 0u) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
146
179
|
let n = c.count;
|
|
147
180
|
let restAt = 7u * n + i * 3u;
|
|
148
181
|
let normalAt = 10u * n + i * 3u;
|
|
@@ -162,7 +195,7 @@ fn clothPose(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
|
162
195
|
q += w * (mat3x3<f32>(m[0].xyz, m[1].xyz, m[2].xyz) * q0);
|
|
163
196
|
}
|
|
164
197
|
}
|
|
165
|
-
let to =
|
|
198
|
+
let to = paces[g].toAt + i * 3u;
|
|
166
199
|
pose[to] = p.x;
|
|
167
200
|
pose[to + 1u] = p.y;
|
|
168
201
|
pose[to + 2u] = p.z;
|
|
@@ -181,7 +214,11 @@ fn clothRest(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
|
181
214
|
if (i >= c.count) {
|
|
182
215
|
return;
|
|
183
216
|
}
|
|
184
|
-
let
|
|
217
|
+
let g = paceAt(i);
|
|
218
|
+
if (paces[g].live == 0u) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
let p = poseOf(paces[g].toAt + i * 3u);
|
|
185
222
|
store(stateAt(POSITION, i), p);
|
|
186
223
|
store(stateAt(START, i), p);
|
|
187
224
|
store(stateAt(VELOCITY, i), vec3<f32>(0.0));
|
|
@@ -194,21 +231,25 @@ fn clothBegin(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
|
194
231
|
if (i >= c.count) {
|
|
195
232
|
return;
|
|
196
233
|
}
|
|
234
|
+
let g = paceAt(i);
|
|
235
|
+
if (paces[g].live == 0u) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
197
238
|
let at = stateAt(POSITION, i);
|
|
198
239
|
let p = load(at);
|
|
199
240
|
store(stateAt(START, i), p);
|
|
200
241
|
if (inverseMass(i) == 0.0) {
|
|
201
|
-
store(at, skinnedAt(i));
|
|
242
|
+
store(at, skinnedAt(i, g));
|
|
202
243
|
return;
|
|
203
244
|
}
|
|
204
|
-
if (
|
|
245
|
+
if (paces[g].carry == 0u) {
|
|
205
246
|
return;
|
|
206
247
|
}
|
|
207
248
|
/* carryParticles: the share of the character's turn about its old origin, and of its move. */
|
|
208
|
-
let turn = mat3x3<f32>(
|
|
209
|
-
let share =
|
|
210
|
-
let x = p -
|
|
211
|
-
store(at, p + (turn * x - x) * share +
|
|
249
|
+
let turn = mat3x3<f32>(paces[g].turn0.xyz, paces[g].turn1.xyz, paces[g].turn2.xyz);
|
|
250
|
+
let share = paces[g].origin.w;
|
|
251
|
+
let x = p - paces[g].origin.xyz;
|
|
252
|
+
store(at, p + (turn * x - x) * share + paces[g].shift.xyz);
|
|
212
253
|
let vAt = stateAt(VELOCITY, i);
|
|
213
254
|
let v = load(vAt);
|
|
214
255
|
store(vAt, v + (turn * v - v) * share);
|
|
@@ -221,6 +262,10 @@ fn clothPredict(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
|
221
262
|
if (i >= c.count) {
|
|
222
263
|
return;
|
|
223
264
|
}
|
|
265
|
+
let g = paceAt(i);
|
|
266
|
+
if (paces[g].live == 0u) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
224
269
|
let at = stateAt(POSITION, i);
|
|
225
270
|
let p = load(at);
|
|
226
271
|
store(stateAt(PREVIOUS, i), p);
|
|
@@ -228,8 +273,8 @@ fn clothPredict(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
|
228
273
|
return;
|
|
229
274
|
}
|
|
230
275
|
let vAt = stateAt(VELOCITY, i);
|
|
231
|
-
let air =
|
|
232
|
-
let v = air + (load(vAt) *
|
|
276
|
+
let air = paces[g].wind.xyz;
|
|
277
|
+
let v = air + (load(vAt) * paces[g].keep - air) * paces[g].dragKeep + paces[g].gravity.xyz * c.h;
|
|
233
278
|
store(vAt, v);
|
|
234
279
|
store(at, p + v * c.h);
|
|
235
280
|
}
|
|
@@ -241,13 +286,17 @@ fn clothDistance(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
|
241
286
|
if (k >= batch.end) {
|
|
242
287
|
return;
|
|
243
288
|
}
|
|
289
|
+
let a = constraints[k * 4u];
|
|
290
|
+
let b = constraints[k * 4u + 1u];
|
|
291
|
+
/* A garment sitting the round out solves nothing, and its next step's first pass resets. */
|
|
292
|
+
if (paces[paceAt(a)].live == 0u) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
244
295
|
/* The first pass of a substep starts the multiplier at nothing, as the CPU's fill(0) does —
|
|
245
296
|
written before any early return, so a skipped constraint does not carry the last one. */
|
|
246
297
|
if (batch.first == 1u) {
|
|
247
298
|
lambda[k] = 0.0;
|
|
248
299
|
}
|
|
249
|
-
let a = constraints[k * 4u];
|
|
250
|
-
let b = constraints[k * 4u + 1u];
|
|
251
300
|
let wa = inverseMass(a);
|
|
252
301
|
let wb = inverseMass(b);
|
|
253
302
|
let w = wa + wb;
|
|
@@ -284,6 +333,9 @@ fn clothBending(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
|
284
333
|
}
|
|
285
334
|
let at = c.distances * 4u + k * 6u;
|
|
286
335
|
let slot = c.distances + k;
|
|
336
|
+
if (paces[paceAt(constraints[at])].live == 0u) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
287
339
|
if (batch.first == 1u) {
|
|
288
340
|
lambda[slot] = 0.0;
|
|
289
341
|
}
|
|
@@ -352,6 +404,9 @@ fn clothTether(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
|
352
404
|
return;
|
|
353
405
|
}
|
|
354
406
|
let at = c.distances * 4u + c.bendings * 6u + k * 3u;
|
|
407
|
+
if (paces[paceAt(constraints[at])].live == 0u) {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
355
410
|
let pAt = stateAt(POSITION, constraints[at]);
|
|
356
411
|
let anchor = load(stateAt(POSITION, constraints[at + 1u]));
|
|
357
412
|
let d = load(pAt) - anchor;
|
|
@@ -380,14 +435,19 @@ fn clothLimit(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
|
380
435
|
if (i >= c.count || inverseMass(i) == 0.0) {
|
|
381
436
|
return;
|
|
382
437
|
}
|
|
438
|
+
let g = paceAt(i);
|
|
439
|
+
if (paces[g].live == 0u) {
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
let limits = paces[g].limits;
|
|
383
443
|
let n = c.count;
|
|
384
444
|
let at = stateAt(POSITION, i);
|
|
385
445
|
var p = load(at);
|
|
386
|
-
let t = skinnedAt(i);
|
|
446
|
+
let t = skinnedAt(i, g);
|
|
387
447
|
/* A max distance below zero is none: the CPU's Infinity, which a device may not be handed. */
|
|
388
448
|
let maxDistance = statics[n + i];
|
|
389
|
-
if ((
|
|
390
|
-
let limit = maxDistance *
|
|
449
|
+
if ((limits & 1u) != 0u && maxDistance >= 0.0) {
|
|
450
|
+
let limit = maxDistance * paces[g].maxDistanceScale;
|
|
391
451
|
let d = p - t;
|
|
392
452
|
let d2 = dot(d, d);
|
|
393
453
|
if (d2 > limit * limit) {
|
|
@@ -395,22 +455,23 @@ fn clothLimit(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
|
395
455
|
}
|
|
396
456
|
}
|
|
397
457
|
let normal = poseOf(6u * n + i * 3u);
|
|
398
|
-
if ((
|
|
458
|
+
if ((limits & 2u) != 0u) {
|
|
399
459
|
let radius = statics[2u * n + i * 2u + 1u];
|
|
400
460
|
if (radius > 0.0) {
|
|
401
461
|
p = pushOut(p, t - normal * (statics[2u * n + i * 2u] + radius), radius);
|
|
402
462
|
}
|
|
403
463
|
}
|
|
404
|
-
if ((
|
|
464
|
+
if ((limits & 4u) != 0u) {
|
|
405
465
|
let radius = statics[4u * n + i * 2u + 1u];
|
|
406
466
|
if (radius > 0.0) {
|
|
407
467
|
p = pushOut(p, t + normal * (statics[4u * n + i * 2u] + radius), radius);
|
|
408
468
|
}
|
|
409
469
|
}
|
|
410
|
-
let pad = statics[6u * n + i] +
|
|
470
|
+
let pad = statics[6u * n + i] + paces[g].margin;
|
|
411
471
|
let ends = c.joints * 16u;
|
|
412
472
|
let radii = ends + c.colliders * 6u;
|
|
413
|
-
|
|
473
|
+
let first = paces[g].colliderBase;
|
|
474
|
+
for (var k = first; k < first + paces[g].colliders; k++) {
|
|
414
475
|
let a = vec3<f32>(frame[ends + k * 6u], frame[ends + k * 6u + 1u], frame[ends + k * 6u + 2u]);
|
|
415
476
|
let e = vec3<f32>(frame[ends + k * 6u + 3u], frame[ends + k * 6u + 4u], frame[ends + k * 6u + 5u]) - a;
|
|
416
477
|
let e2 = dot(e, e);
|
|
@@ -432,6 +493,9 @@ fn clothFinish(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
|
432
493
|
if (i >= c.count) {
|
|
433
494
|
return;
|
|
434
495
|
}
|
|
496
|
+
if (paces[paceAt(i)].live == 0u) {
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
435
499
|
let vAt = stateAt(VELOCITY, i);
|
|
436
500
|
if (inverseMass(i) == 0.0) {
|
|
437
501
|
store(vAt, vec3<f32>(0.0));
|
|
@@ -447,24 +511,34 @@ fn clothBlend(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
|
447
511
|
if (i >= c.count) {
|
|
448
512
|
return;
|
|
449
513
|
}
|
|
450
|
-
|
|
514
|
+
/* A blend of 0 is none, not a last step of one: see ClothDevice.step. */
|
|
515
|
+
let g = paceAt(i);
|
|
516
|
+
let blend = paces[g].blend;
|
|
517
|
+
if (paces[g].live == 0u || blend <= 0.0) {
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
let t = skinnedAt(i, g);
|
|
451
521
|
let at = stateAt(POSITION, i);
|
|
452
|
-
store(at, t + (load(at) - t) *
|
|
522
|
+
store(at, t + (load(at) - t) * blend);
|
|
453
523
|
let vAt = stateAt(VELOCITY, i);
|
|
454
|
-
store(vAt, load(vAt) *
|
|
524
|
+
store(vAt, load(vAt) * blend);
|
|
455
525
|
}
|
|
456
526
|
|
|
457
527
|
@group(1) @binding(0) var output: texture_storage_2d<rgba32float, write>;
|
|
458
528
|
|
|
459
|
-
/* SkinnedCloth.interpolate, into the particle texture the vertex stage reads
|
|
529
|
+
/* SkinnedCloth.interpolate, into the particle texture the vertex stage reads: one garment's, whose
|
|
530
|
+
particles are batch.begin to batch.end and whose record is batch.first's. */
|
|
460
531
|
@compute @workgroup_size(64)
|
|
461
532
|
fn clothPublish(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
462
|
-
let i = id.x;
|
|
463
|
-
if (i >=
|
|
533
|
+
let i = batch.begin + id.x;
|
|
534
|
+
if (i >= batch.end) {
|
|
464
535
|
return;
|
|
465
536
|
}
|
|
537
|
+
let g = round.at + batch.first;
|
|
466
538
|
let a = load(stateAt(START, i));
|
|
467
|
-
let p = a + (load(stateAt(POSITION, i)) - a) *
|
|
468
|
-
|
|
539
|
+
let p = a + (load(stateAt(POSITION, i)) - a) * paces[g].alpha;
|
|
540
|
+
let local = id.x;
|
|
541
|
+
let width = paces[g].width;
|
|
542
|
+
textureStore(output, vec2<u32>(local % width, local / width), vec4<f32>(p, 0.0));
|
|
469
543
|
}
|
|
470
544
|
`;
|
|
@@ -29,8 +29,8 @@ import { SkinPaletteTexture } from './skinPaletteTexture.ts';
|
|
|
29
29
|
* different rig at every set — the comparison is what tells the two apart.
|
|
30
30
|
*
|
|
31
31
|
* **It was capped at 128 until 4.8.6, and the cap declined draws.** A stage of three dozen idling
|
|
32
|
-
* extras beside two
|
|
33
|
-
* the consumer stood its crowd in the bind pose. The ring now holds as many palettes as a frame
|
|
32
|
+
* extras beside two characters filled it in one frame and every skinned draw past it was refused,
|
|
33
|
+
* so the consumer stood its crowd in the bind pose. The ring now holds as many palettes as a frame
|
|
34
34
|
* holds draws (`RenderQuality.drawsPerFrame`), since no frame can bind more palettes than it draws;
|
|
35
35
|
* a slot still allocates its texture only the first time a frame reaches it, so a scene with two
|
|
36
36
|
* characters holds two. **What it costs** is a texture and a cached bind group a slot, 1.5 KB for a
|
|
@@ -46,8 +46,12 @@ import { SkinPaletteTexture } from './skinPaletteTexture.ts';
|
|
|
46
46
|
*/
|
|
47
47
|
export class SkinPaletteRing {
|
|
48
48
|
private readonly slots: SkinPaletteTexture[] = [];
|
|
49
|
-
/**
|
|
49
|
+
/**
|
|
50
|
+
* What each slot was last written with, for the comparison that lets a pass reuse it: a copy
|
|
51
|
+
* that grows with the largest rig the slot has held, and how much of it the last rig filled.
|
|
52
|
+
*/
|
|
50
53
|
private readonly held: Float32Array[] = [];
|
|
54
|
+
private readonly heldLength: number[] = [];
|
|
51
55
|
/** The slot each palette array last went into, by identity. Weak, so a caller's array can go. */
|
|
52
56
|
private readonly lastSlot = new WeakMap<Float32Array, number>();
|
|
53
57
|
private used = 0;
|
|
@@ -119,12 +123,13 @@ export class SkinPaletteRing {
|
|
|
119
123
|
slot.update(device, palette);
|
|
120
124
|
this.uploads += 1;
|
|
121
125
|
let copy = this.held[at];
|
|
122
|
-
if (copy === undefined || copy.length
|
|
123
|
-
/* Once per slot and
|
|
126
|
+
if (copy === undefined || copy.length < palette.length) {
|
|
127
|
+
/* Once per slot and larger rig, the way the slot's own texture is: never per frame. */
|
|
124
128
|
copy = new Float32Array(palette.length);
|
|
125
129
|
this.held[at] = copy;
|
|
126
130
|
}
|
|
127
131
|
copy.set(palette);
|
|
132
|
+
this.heldLength[at] = palette.length;
|
|
128
133
|
this.lastSlot.set(palette, at);
|
|
129
134
|
return at;
|
|
130
135
|
}
|
|
@@ -138,14 +143,15 @@ export class SkinPaletteRing {
|
|
|
138
143
|
for (const slot of this.slots) slot.dispose();
|
|
139
144
|
this.slots.length = 0;
|
|
140
145
|
this.held.length = 0;
|
|
146
|
+
this.heldLength.length = 0;
|
|
141
147
|
this.used = 0;
|
|
142
148
|
}
|
|
143
149
|
|
|
144
150
|
/** Whether a slot was last written with exactly these numbers. */
|
|
145
151
|
private holds(slot: number, palette: Float32Array): boolean {
|
|
146
152
|
const copy = this.held[slot];
|
|
147
|
-
if (copy === undefined ||
|
|
148
|
-
for (let i = 0; i <
|
|
153
|
+
if (copy === undefined || this.heldLength[slot] !== palette.length) return false;
|
|
154
|
+
for (let i = 0; i < palette.length; i++) if (copy[i] !== palette[i]) return false;
|
|
149
155
|
return true;
|
|
150
156
|
}
|
|
151
157
|
}
|
|
@@ -22,6 +22,12 @@ const TEXTURE_USAGE = {
|
|
|
22
22
|
|
|
23
23
|
export class SkinPaletteTexture {
|
|
24
24
|
private texture: GPUTexture | null = null;
|
|
25
|
+
/**
|
|
26
|
+
* How many joints the texture has room for, which is the most any rig in this slot has had.
|
|
27
|
+
* **It grows and never shrinks**: the shader reads a joint by index, so a texture wider than the
|
|
28
|
+
* rig is read exactly as one that fits, and a slot that a 10-joint prop and a 296-joint character
|
|
29
|
+
* take in turn keeps one texture rather than making one at every change of rig.
|
|
30
|
+
*/
|
|
25
31
|
private joints = 0;
|
|
26
32
|
/**
|
|
27
33
|
* The view, cached rather than created per call.
|
|
@@ -38,7 +44,7 @@ export class SkinPaletteTexture {
|
|
|
38
44
|
const joints = palette.length / 16;
|
|
39
45
|
const width = paletteTextureWidth(joints);
|
|
40
46
|
|
|
41
|
-
if (this.texture === null ||
|
|
47
|
+
if (this.texture === null || joints > this.joints) {
|
|
42
48
|
this.texture?.destroy();
|
|
43
49
|
this.cachedView = null;
|
|
44
50
|
this.texture = device.createTexture({
|