@driftengine/core 4.8.3 → 4.8.4

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.
Files changed (178) hide show
  1. package/CHANGELOG.json +71 -0
  2. package/README.md +1 -1
  3. package/dist/geometry/meshConcat.js +2 -0
  4. package/dist/index.d.ts +10 -4
  5. package/dist/index.js +16 -1
  6. package/dist/math/scalar.js +1 -1
  7. package/dist/render/anisotropicLobe.d.ts +7 -0
  8. package/dist/render/anisotropicLobe.js +33 -0
  9. package/dist/render/backend/api.d.ts +41 -4
  10. package/dist/render/backend/select.js +8 -0
  11. package/dist/render/backend/webgl2/clothTextures.d.ts +27 -0
  12. package/dist/render/backend/webgl2/clothTextures.js +93 -0
  13. package/dist/render/backend/webgl2/renderer.d.ts +136 -3
  14. package/dist/render/backend/webgl2/renderer.js +604 -63
  15. package/dist/render/backend/webgl2/skinScatter.d.ts +50 -0
  16. package/dist/render/backend/webgl2/skinScatter.js +256 -0
  17. package/dist/render/backend/webgpu/buffers.d.ts +25 -11
  18. package/dist/render/backend/webgpu/buffers.js +98 -49
  19. package/dist/render/backend/webgpu/clothSolvePack.d.ts +27 -0
  20. package/dist/render/backend/webgpu/clothSolvePack.js +129 -0
  21. package/dist/render/backend/webgpu/clothTextures.d.ts +68 -0
  22. package/dist/render/backend/webgpu/clothTextures.js +145 -0
  23. package/dist/render/backend/webgpu/compressedUpload.d.ts +18 -0
  24. package/dist/render/backend/webgpu/compressedUpload.js +38 -0
  25. package/dist/render/backend/webgpu/computeHost.d.ts +21 -0
  26. package/dist/render/backend/webgpu/computeHost.js +5 -0
  27. package/dist/render/backend/webgpu/depthPass.d.ts +16 -6
  28. package/dist/render/backend/webgpu/depthPass.js +39 -9
  29. package/dist/render/backend/webgpu/drawCommand.js +6 -2
  30. package/dist/render/backend/webgpu/flatPass.d.ts +38 -4
  31. package/dist/render/backend/webgpu/flatPass.js +109 -12
  32. package/dist/render/backend/webgpu/gpuSkinnedCloth.d.ts +74 -0
  33. package/dist/render/backend/webgpu/gpuSkinnedCloth.js +452 -0
  34. package/dist/render/backend/webgpu/motionPass.d.ts +20 -0
  35. package/dist/render/backend/webgpu/motionPass.js +106 -9
  36. package/dist/render/backend/webgpu/postPass.d.ts +3 -1
  37. package/dist/render/backend/webgpu/postPass.js +6 -3
  38. package/dist/render/backend/webgpu/renderer.d.ts +113 -5
  39. package/dist/render/backend/webgpu/renderer.js +498 -48
  40. package/dist/render/backend/webgpu/shaders/clothSolve.wgsl.d.ts +33 -0
  41. package/dist/render/backend/webgpu/shaders/clothSolve.wgsl.js +469 -0
  42. package/dist/render/backend/webgpu/skinScatterPass.d.ts +51 -0
  43. package/dist/render/backend/webgpu/skinScatterPass.js +253 -0
  44. package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +4 -1
  45. package/dist/render/backend/webgpu/surfaceTexturePass.js +37 -12
  46. package/dist/render/clothBindingData.d.ts +41 -0
  47. package/dist/render/clothBindingData.js +72 -0
  48. package/dist/render/clothPlacement.d.ts +25 -0
  49. package/dist/render/clothPlacement.js +85 -0
  50. package/dist/render/compressedSource.d.ts +66 -0
  51. package/dist/render/compressedSource.js +138 -0
  52. package/dist/render/cutoutCaster.d.ts +2 -0
  53. package/dist/render/cutoutCaster.js +2 -0
  54. package/dist/render/cutoutDither.d.ts +51 -0
  55. package/dist/render/cutoutDither.js +90 -0
  56. package/dist/render/eyeRefraction.d.ts +35 -0
  57. package/dist/render/eyeRefraction.js +40 -0
  58. package/dist/render/glCompressed.d.ts +27 -0
  59. package/dist/render/glCompressed.js +53 -0
  60. package/dist/render/hairLobes.d.ts +70 -0
  61. package/dist/render/hairLobes.js +120 -0
  62. package/dist/render/lightBudget.d.ts +22 -0
  63. package/dist/render/lightBudget.js +22 -0
  64. package/dist/render/mesh.d.ts +7 -0
  65. package/dist/render/mesh.js +24 -0
  66. package/dist/render/recon/motionVectors.d.ts +4 -2
  67. package/dist/render/recon/motionVectors.js +6 -3
  68. package/dist/render/renderQuality.d.ts +20 -0
  69. package/dist/render/renderQuality.js +5 -0
  70. package/dist/render/rendererHarness.js +4 -0
  71. package/dist/render/sceneTarget.d.ts +12 -0
  72. package/dist/render/sceneTarget.js +14 -0
  73. package/dist/render/shaders/clothBinding.d.ts +22 -0
  74. package/dist/render/shaders/clothBinding.js +80 -0
  75. package/dist/render/shaders/depth.js +42 -6
  76. package/dist/render/shaders/flat/anisotropic.d.ts +15 -0
  77. package/dist/render/shaders/flat/anisotropic.js +68 -0
  78. package/dist/render/shaders/flat/eye.d.ts +1 -0
  79. package/dist/render/shaders/flat/eye.js +81 -0
  80. package/dist/render/shaders/flat/hair.d.ts +1 -0
  81. package/dist/render/shaders/flat/hair.js +101 -0
  82. package/dist/render/shaders/flat/index.js +36 -2
  83. package/dist/render/shaders/flat/main.d.ts +1 -1
  84. package/dist/render/shaders/flat/main.js +113 -17
  85. package/dist/render/shaders/flat/models.d.ts +14 -0
  86. package/dist/render/shaders/flat/models.js +273 -0
  87. package/dist/render/shaders/flat/preamble.js +26 -24
  88. package/dist/render/shaders/flat/skin.d.ts +1 -0
  89. package/dist/render/shaders/flat/skin.js +114 -0
  90. package/dist/render/shaders/generated/depth.wgsl.d.ts +38 -16
  91. package/dist/render/shaders/generated/depth.wgsl.js +38 -16
  92. package/dist/render/shaders/generated/flat.wgsl.d.ts +1790 -1704
  93. package/dist/render/shaders/generated/flat.wgsl.js +1828 -1742
  94. package/dist/render/shaders/generated/skinBlur.wgsl.d.ts +48 -0
  95. package/dist/render/shaders/generated/skinBlur.wgsl.js +54 -0
  96. package/dist/render/shaders/recon/motion.wgsl.d.ts +1 -1
  97. package/dist/render/shaders/recon/motion.wgsl.js +102 -0
  98. package/dist/render/shaders/skinBlur.d.ts +1 -0
  99. package/dist/render/shaders/skinBlur.js +103 -0
  100. package/dist/render/shaders/skinning.d.ts +3 -1
  101. package/dist/render/shaders/skinning.js +31 -4
  102. package/dist/render/shadowCasters.d.ts +13 -1
  103. package/dist/render/skinBlur.d.ts +41 -0
  104. package/dist/render/skinBlur.js +49 -0
  105. package/dist/render/skinScatter.d.ts +67 -0
  106. package/dist/render/skinScatter.js +80 -0
  107. package/dist/render/skinnedClothRun.d.ts +26 -0
  108. package/dist/render/skinnedClothRun.js +84 -0
  109. package/dist/render/surfaceModel.d.ts +129 -0
  110. package/dist/render/surfaceModel.js +152 -0
  111. package/dist/render/surfaceTexture.d.ts +44 -4
  112. package/dist/render/surfaceTexture.js +60 -46
  113. package/dist/render/vertexDefaults.js +7 -0
  114. package/package.json +6 -6
  115. package/src/geometry/meshConcat.ts +2 -0
  116. package/src/index.ts +40 -1
  117. package/src/math/scalar.ts +1 -1
  118. package/src/render/anisotropicLobe.ts +41 -0
  119. package/src/render/backend/api.ts +52 -3
  120. package/src/render/backend/select.ts +8 -0
  121. package/src/render/backend/webgl2/clothTextures.ts +120 -0
  122. package/src/render/backend/webgl2/renderer.ts +693 -64
  123. package/src/render/backend/webgl2/skinScatter.ts +309 -0
  124. package/src/render/backend/webgpu/buffers.ts +137 -63
  125. package/src/render/backend/webgpu/clothSolvePack.ts +161 -0
  126. package/src/render/backend/webgpu/clothTextures.ts +194 -0
  127. package/src/render/backend/webgpu/compressedUpload.ts +65 -0
  128. package/src/render/backend/webgpu/computeHost.ts +25 -0
  129. package/src/render/backend/webgpu/depthPass.ts +39 -7
  130. package/src/render/backend/webgpu/drawCommand.ts +6 -2
  131. package/src/render/backend/webgpu/flatPass.ts +145 -7
  132. package/src/render/backend/webgpu/gpuSkinnedCloth.ts +502 -0
  133. package/src/render/backend/webgpu/motionPass.ts +128 -9
  134. package/src/render/backend/webgpu/postPass.ts +5 -1
  135. package/src/render/backend/webgpu/renderer.ts +663 -43
  136. package/src/render/backend/webgpu/shaders/clothSolve.wgsl.ts +470 -0
  137. package/src/render/backend/webgpu/skinScatterPass.ts +309 -0
  138. package/src/render/backend/webgpu/surfaceTexturePass.ts +42 -12
  139. package/src/render/clothBindingData.ts +89 -0
  140. package/src/render/clothPlacement.ts +114 -0
  141. package/src/render/compressedSource.ts +198 -0
  142. package/src/render/cutoutCaster.ts +5 -0
  143. package/src/render/cutoutDither.ts +99 -0
  144. package/src/render/eyeRefraction.ts +72 -0
  145. package/src/render/glCompressed.ts +86 -0
  146. package/src/render/hairLobes.ts +188 -0
  147. package/src/render/lightBudget.ts +25 -0
  148. package/src/render/mesh.ts +23 -0
  149. package/src/render/recon/motionVectors.ts +6 -3
  150. package/src/render/renderQuality.ts +28 -0
  151. package/src/render/rendererHarness.ts +4 -0
  152. package/src/render/sceneTarget.ts +21 -0
  153. package/src/render/shaders/clothBinding.ts +81 -0
  154. package/src/render/shaders/depth.ts +42 -6
  155. package/src/render/shaders/flat/anisotropic.ts +68 -0
  156. package/src/render/shaders/flat/eye.ts +82 -0
  157. package/src/render/shaders/flat/hair.ts +102 -0
  158. package/src/render/shaders/flat/index.ts +36 -2
  159. package/src/render/shaders/flat/main.ts +113 -17
  160. package/src/render/shaders/flat/models.ts +286 -0
  161. package/src/render/shaders/flat/preamble.ts +26 -24
  162. package/src/render/shaders/flat/skin.ts +116 -0
  163. package/src/render/shaders/generated/depth.wgsl.ts +38 -16
  164. package/src/render/shaders/generated/flat.wgsl.ts +1828 -1742
  165. package/src/render/shaders/generated/skinBlur.wgsl.ts +56 -0
  166. package/src/render/shaders/recon/motion.wgsl.ts +102 -0
  167. package/src/render/shaders/skinBlur.ts +105 -0
  168. package/src/render/shaders/skinning.ts +31 -4
  169. package/src/render/shadowCasters.ts +13 -0
  170. package/src/render/skinBlur.ts +53 -0
  171. package/src/render/skinScatter.ts +92 -0
  172. package/src/render/skinnedClothRun.ts +128 -0
  173. package/src/render/surfaceModel.ts +274 -0
  174. package/src/render/surfaceTexture.ts +123 -63
  175. package/src/render/vertexDefaults.ts +7 -0
  176. package/dist/math/exact.d.ts +0 -76
  177. package/dist/math/exact.js +0 -327
  178. package/src/math/exact.ts +0 -340
@@ -1,4 +1,7 @@
1
+ import type { SurfaceModelKind } from '../../surfaceModel.ts';
2
+ import type { SkinHalf } from '../../shaders/flat/models.ts';
1
3
  import type { PipelineCache } from './pipelineCache.ts';
4
+ import type { ClothViews } from './clothTextures.ts';
2
5
  /**
3
6
  * The flat pipeline: the shader that draws the world.
4
7
  *
@@ -65,6 +68,13 @@ export interface StageBindings {
65
68
  export declare function flatVertexKey(skinned: boolean, morphed: boolean, instanced?: boolean): string;
66
69
  /** Everything the generator recorded about one variant of the vertex stage. */
67
70
  export declare function flatVertexBindings(skinned: boolean, morphed?: boolean, instanced?: boolean): StageBindings;
71
+ /**
72
+ * A vertex stage's constants, keyed by each override's **id** as the fragment's are: `SKIN_EIGHT` in
73
+ * a skinned stage, nothing in any other. Every override a stage declares is set, and one this does
74
+ * not know is refused here rather than defaulted. Shared with the shadow and glass-tint casters,
75
+ * whose skinned stages declare the same switch.
76
+ */
77
+ export declare function vertexConstants(bindings: StageBindings, skinEight: boolean, cloth?: boolean): Record<string, number>;
68
78
  export declare const FLAT_VERT_FIELDS: {
69
79
  readonly uViewProj: {
70
80
  readonly offset: 0;
@@ -152,7 +162,7 @@ export declare function createFlatBindGroupLayout(device: GPUDevice, variant: Fl
152
162
  *
153
163
  * `resolve` is asked for a view by the shader's own name for it, so a caller supplies the
154
164
  * shadow maps it has and a stand-in for the rest. **Every declared binding must be filled
155
- * even when the shader never samples it** — `uAlbedoEnabled` is zero for nearly all geometry
165
+ * even when the shader never samples it** — the albedo's flag is zero for nearly all geometry
156
166
  * and WebGPU still requires something there, which is why `renderer.ts` keeps an
157
167
  * `emptyTexture2D` for the same reason on the other side.
158
168
  */
@@ -163,7 +173,9 @@ export declare function createFlatBindGroup(device: GPUDevice, layout: GPUBindGr
163
173
  /** The palette view for a skinned bind group, or null for an unskinned one. */
164
174
  palette?: GPUTextureView | null,
165
175
  /** The delta view for a morphed bind group, or null for an unmorphed one. */
166
- deltas?: GPUTextureView | null): GPUBindGroup;
176
+ deltas?: GPUTextureView | null,
177
+ /** A skinned bind group's cloth views — the draw's, or the stand-in where it sets none. */
178
+ cloth?: ClothViews | null): GPUBindGroup;
167
179
  /**
168
180
  * The pipeline, cached by the state that distinguishes it.
169
181
  *
@@ -206,7 +218,23 @@ instanced?: boolean,
206
218
  /** Which order-independent buffer this pipeline writes, if any. The key must carry it. */
207
219
  oit?: OitTarget,
208
220
  /** Culls nothing, for a surface seen from both faces. The key must carry it: `|2s`. */
209
- doubleSided?: boolean): GPURenderPipeline;
221
+ doubleSided?: boolean,
222
+ /**
223
+ * Turns the fragment's alpha into the pixel's samples, for a dithered cutout in a multisampled
224
+ * frame with no temporal resolve. The key must carry it: `|a2c`. See `cutoutDither.ts`.
225
+ */
226
+ alphaToCoverage?: boolean,
227
+ /**
228
+ * Whether a skinned pipeline reads the second four influences: the vertex stage's `SKIN_EIGHT`.
229
+ * The key must carry it: `|s8`. See `skinning.ts`.
230
+ */
231
+ skinEight?: boolean,
232
+ /** Whether its vertex stage places vertices by a cloth binding. See `clothBinding.ts`. */
233
+ cloth?: boolean,
234
+ /** Which shading model its fragment stage shades by, null the standard. The key must carry it. */
235
+ model?: SurfaceModelKind | null,
236
+ /** Which half of a skin it draws. The key must carry it: `|ss` or `|sd`. See `SkinHalf`. */
237
+ skinPass?: SkinHalf): GPURenderPipeline;
210
238
  /**
211
239
  * The same pipeline, compiled off the main thread.
212
240
  *
@@ -220,6 +248,12 @@ export declare function flatPipelineAsync(cache: PipelineCache, device: GPUDevic
220
248
  /** Whether this pipeline reads a joint palette. See `FlatVertexOptions`. */
221
249
  skinned?: boolean,
222
250
  /** Whether this pipeline reads morph deltas. See `FlatVertexOptions`. */
223
- morphed?: boolean): Promise<GPURenderPipeline>;
251
+ morphed?: boolean,
252
+ /** Whether the skinned stage reads the second four influences. See `flatPipeline`. */
253
+ skinEight?: boolean,
254
+ /** Whether its vertex stage places vertices by a cloth binding. See `clothBinding.ts`. */
255
+ cloth?: boolean,
256
+ /** Which shading model its fragment stage shades by. See `flatPipeline`. */
257
+ model?: SurfaceModelKind | null): Promise<GPURenderPipeline>;
224
258
  /** Which of the two order-independent buffers a pipeline writes, or neither. */
225
259
  export type OitTarget = 'none' | 'accum' | 'reveal';
@@ -1,3 +1,4 @@
1
+ import { SURFACE_MODEL_SWITCH } from '../../surfaceModel.js';
1
2
  import { DEPTH_COMPARE, DEPTH_FORMAT, depthOffsetForLayer } from '../../depthConvention.js';
2
3
  import { FLAT_BINDINGS, FLAT_FRAG_WGSL, FLAT_VERT_WGSL, } from '../../shaders/generated/flat.wgsl.js';
3
4
  import { vertexBufferLayouts } from './buffers.js';
@@ -9,6 +10,7 @@ const SURFACE_MAPS = new Set([
9
10
  'uNormalMap',
10
11
  'uOrmMap',
11
12
  'uEmissiveMap',
13
+ 'uModelMap',
12
14
  ]);
13
15
  /**
14
16
  * The key for a set of flags.
@@ -68,6 +70,35 @@ export function flatVertexBindings(skinned, morphed = false, instanced = false)
68
70
  return found;
69
71
  }
70
72
  const PLAIN_VERTEX = flatVertexBindings(false);
73
+ /**
74
+ * A vertex stage's constants, keyed by each override's **id** as the fragment's are: `SKIN_EIGHT` in
75
+ * a skinned stage, nothing in any other. Every override a stage declares is set, and one this does
76
+ * not know is refused here rather than defaulted. Shared with the shadow and glass-tint casters,
77
+ * whose skinned stages declare the same switch.
78
+ */
79
+ export function vertexConstants(bindings, skinEight, cloth = false) {
80
+ const constants = {};
81
+ for (const [name, id] of Object.entries(bindings.overrides ?? {})) {
82
+ if (name === 'SKIN_EIGHT')
83
+ constants[String(id)] = skinEight ? 1 : 0;
84
+ else if (name === 'CLOTH_BOUND')
85
+ constants[String(id)] = cloth ? 1 : 0;
86
+ else
87
+ throw new Error(`flatPass: a vertex stage declares a switch "${name}" nothing sets`);
88
+ }
89
+ return constants;
90
+ }
91
+ /** Where a skinned stage declares the cloth binding's three textures: binding, particles, rest. */
92
+ function clothBindings(skinned, morphed) {
93
+ const textures = flatVertexBindings(skinned, morphed).textures;
94
+ const at = (name) => {
95
+ const found = textures[name];
96
+ if (found === undefined)
97
+ throw new Error(`flatPass: the skinned vertex shader declares no ${name}`);
98
+ return found.texture;
99
+ };
100
+ return [at('uClothBinding'), at('uClothParticles'), at('uClothRest')];
101
+ }
71
102
  /*
72
103
  * **A variant may drop a field; it may never move one.**
73
104
  *
@@ -124,13 +155,28 @@ export function flatFragmentBindings(variant) {
124
155
  * "GLASS_SHADOWS" not found*, and the frame drew nothing. Every override the variant declares is
125
156
  * set, so a switch added to the shader and not to the cache is refused here rather than defaulted.
126
157
  */
127
- function flatFragmentConstants(variant, cache) {
158
+ function flatFragmentConstants(variant, cache, model, skinPass = 'whole') {
128
159
  const overrides = flatFragmentBindings(variant).overrides;
129
160
  if (overrides?.['GLASS_SHADOWS'] === undefined) {
130
161
  throw new Error(`flatPass: variant "${variant}" has no glass switch`);
131
162
  }
163
+ const modelSwitch = model === null ? null : SURFACE_MODEL_SWITCH[model];
132
164
  const constants = {};
133
165
  for (const [name, id] of Object.entries(overrides)) {
166
+ /* A model's switch is the pipeline's own, set from its key rather than from the cache. */
167
+ if (name.startsWith('MODEL_')) {
168
+ constants[String(id)] = name === modelSwitch ? 1 : 0;
169
+ continue;
170
+ }
171
+ /* Skin's two halves under the screen-space blur, set from the key as a model's switch is. */
172
+ if (name === 'SKIN_SCREEN' || name === 'SKIN_DIFFUSE') {
173
+ constants[String(id)] =
174
+ (name === 'SKIN_SCREEN' && skinPass === 'scene') ||
175
+ (name === 'SKIN_DIFFUSE' && skinPass === 'diffuse')
176
+ ? 1
177
+ : 0;
178
+ continue;
179
+ }
134
180
  if (!(name in cache.litSwitches)) {
135
181
  throw new Error(`flatPass: variant "${variant}" declares a switch "${name}" no cache sets`);
136
182
  }
@@ -298,6 +344,15 @@ export function createFlatBindGroupLayout(device, variant, skinned = false, morp
298
344
  visibility: VISIBILITY_VERTEX,
299
345
  texture: { sampleType: 'unfilterable-float' },
300
346
  });
347
+ /* The cloth binding's three textures, declared by every skinned stage whether a draw sets a
348
+ cloth or not; see `clothBinding.ts`. */
349
+ for (const binding of clothBindings(skinned, morphed)) {
350
+ entries.push({
351
+ binding,
352
+ visibility: VISIBILITY_VERTEX,
353
+ texture: { sampleType: 'unfilterable-float' },
354
+ });
355
+ }
301
356
  }
302
357
  return device.createBindGroupLayout({
303
358
  label: `flat.layout:${variant}|${flatVertexKey(skinned, morphed)}`,
@@ -309,7 +364,7 @@ export function createFlatBindGroupLayout(device, variant, skinned = false, morp
309
364
  *
310
365
  * `resolve` is asked for a view by the shader's own name for it, so a caller supplies the
311
366
  * shadow maps it has and a stand-in for the rest. **Every declared binding must be filled
312
- * even when the shader never samples it** — `uAlbedoEnabled` is zero for nearly all geometry
367
+ * even when the shader never samples it** — the albedo's flag is zero for nearly all geometry
313
368
  * and WebGPU still requires something there, which is why `renderer.ts` keeps an
314
369
  * `emptyTexture2D` for the same reason on the other side.
315
370
  */
@@ -317,7 +372,9 @@ export function createFlatBindGroup(device, layout, variant, perDraw, perFrame,
317
372
  /** The palette view for a skinned bind group, or null for an unskinned one. */
318
373
  palette = null,
319
374
  /** The delta view for a morphed bind group, or null for an unmorphed one. */
320
- deltas = null) {
375
+ deltas = null,
376
+ /** A skinned bind group's cloth views — the draw's, or the stand-in where it sets none. */
377
+ cloth = null) {
321
378
  const fragment = flatFragmentBindings(variant);
322
379
  const entries = [
323
380
  {
@@ -351,6 +408,13 @@ deltas = null) {
351
408
  throw new Error('flatPass: the skinned vertex shader declares no uJointPalette');
352
409
  }
353
410
  entries.push({ binding: binding.texture, resource: palette });
411
+ if (cloth === null) {
412
+ throw new Error('flatPass: a skinned bind group needs cloth views, the stand-in at the least');
413
+ }
414
+ const [bindingAt, particlesAt, restAt] = clothBindings(true, deltas !== null);
415
+ entries.push({ binding: bindingAt, resource: cloth.binding });
416
+ entries.push({ binding: particlesAt, resource: cloth.particles });
417
+ entries.push({ binding: restAt, resource: cloth.rest });
354
418
  }
355
419
  return device.createBindGroup({
356
420
  label: `flat.bindGroup:${variant}|${flatVertexKey(palette !== null, deltas !== null)}`,
@@ -400,8 +464,24 @@ instanced = false,
400
464
  /** Which order-independent buffer this pipeline writes, if any. The key must carry it. */
401
465
  oit = 'none',
402
466
  /** Culls nothing, for a surface seen from both faces. The key must carry it: `|2s`. */
403
- doubleSided = false) {
404
- return cache.get(key, () => flatDescriptor(cache, device, layout, variant, key, present, translucent, skinned, morphed, depthWrite, depthLayer, instanced, oit, doubleSided), true);
467
+ doubleSided = false,
468
+ /**
469
+ * Turns the fragment's alpha into the pixel's samples, for a dithered cutout in a multisampled
470
+ * frame with no temporal resolve. The key must carry it: `|a2c`. See `cutoutDither.ts`.
471
+ */
472
+ alphaToCoverage = false,
473
+ /**
474
+ * Whether a skinned pipeline reads the second four influences: the vertex stage's `SKIN_EIGHT`.
475
+ * The key must carry it: `|s8`. See `skinning.ts`.
476
+ */
477
+ skinEight = false,
478
+ /** Whether its vertex stage places vertices by a cloth binding. See `clothBinding.ts`. */
479
+ cloth = false,
480
+ /** Which shading model its fragment stage shades by, null the standard. The key must carry it. */
481
+ model = null,
482
+ /** Which half of a skin it draws. The key must carry it: `|ss` or `|sd`. See `SkinHalf`. */
483
+ skinPass = 'whole') {
484
+ return cache.get(key, () => flatDescriptor(cache, device, layout, variant, key, present, translucent, skinned, morphed, depthWrite, depthLayer, instanced, oit, doubleSided, alphaToCoverage, skinEight, cloth, model, skinPass), true);
405
485
  }
406
486
  /**
407
487
  * The same pipeline, compiled off the main thread.
@@ -416,8 +496,14 @@ export function flatPipelineAsync(cache, device, layout, variant, key, present,
416
496
  /** Whether this pipeline reads a joint palette. See `FlatVertexOptions`. */
417
497
  skinned = false,
418
498
  /** Whether this pipeline reads morph deltas. See `FlatVertexOptions`. */
419
- morphed = false) {
420
- return cache.getAsync(key, () => flatDescriptor(cache, device, layout, variant, key, present, translucent, skinned, morphed), true);
499
+ morphed = false,
500
+ /** Whether the skinned stage reads the second four influences. See `flatPipeline`. */
501
+ skinEight = false,
502
+ /** Whether its vertex stage places vertices by a cloth binding. See `clothBinding.ts`. */
503
+ cloth = false,
504
+ /** Which shading model its fragment stage shades by. See `flatPipeline`. */
505
+ model = null) {
506
+ return cache.getAsync(key, () => flatDescriptor(cache, device, layout, variant, key, present, translucent, skinned, morphed, true, 0, false, 'none', false, false, skinEight, cloth, model), true);
421
507
  }
422
508
  /**
423
509
  * The colour target for an order-independent pass, or null where this is an ordinary draw.
@@ -473,8 +559,11 @@ instanced = false,
473
559
  */
474
560
  oit = 'none',
475
561
  /** Culls nothing: a surface seen from both faces. */
476
- doubleSided = false) {
562
+ doubleSided = false, alphaToCoverage = false, skinEight = false,
563
+ /** Whether its vertex stage places vertices by a cloth binding. See `clothBinding.ts`. */
564
+ cloth = false, model = null, skinPass = 'whole') {
477
565
  const offset = depthOffsetForLayer(depthLayer);
566
+ const diffuseAlone = skinPass === 'diffuse';
478
567
  return {
479
568
  label: key,
480
569
  layout: device.createPipelineLayout({ bindGroupLayouts: [layout] }),
@@ -490,6 +579,7 @@ doubleSided = false) {
490
579
  }),
491
580
  entryPoint: 'main',
492
581
  buffers: vertexBufferLayouts(present, instanced),
582
+ constants: vertexConstants(flatVertexBindings(skinned, morphed, instanced), skinEight, cloth),
493
583
  },
494
584
  fragment: {
495
585
  module: shaderModule(device, {
@@ -498,7 +588,7 @@ doubleSided = false) {
498
588
  }),
499
589
  entryPoint: 'main',
500
590
  /* Every variant declares it, so every lit pipeline may set it: see `PipelineCache`. */
501
- constants: flatFragmentConstants(variant, cache),
591
+ constants: flatFragmentConstants(variant, cache, model, skinPass),
502
592
  targets: [
503
593
  oitTarget(oit) ??
504
594
  (translucent === 'additive'
@@ -525,7 +615,13 @@ doubleSided = false) {
525
615
  ],
526
616
  },
527
617
  primitive: { topology: 'triangle-list', cullMode: doubleSided ? 'none' : 'back' },
528
- multisample: { count: cache.sampleCount },
618
+ /* Coverage only where a sample count can carry it: WebGPU refuses it at one sample. */
619
+ multisample: {
620
+ count: cache.sampleCount,
621
+ ...(alphaToCoverage && cache.sampleCount > 1 && !diffuseAlone
622
+ ? { alphaToCoverageEnabled: true }
623
+ : {}),
624
+ },
529
625
  /*
530
626
  * `less`, matching the WebGL2 path's `LESS` rather than `LEQUAL`, and for the reason
531
627
  * `drawMesh` documents there: under `LEQUAL` two coplanar surfaces do not merely tie,
@@ -533,8 +629,9 @@ doubleSided = false) {
533
629
  */
534
630
  depthStencil: {
535
631
  format: DEPTH_FORMAT,
536
- depthWriteEnabled: depthWrite,
537
- depthCompare: DEPTH_COMPARE,
632
+ /* The diffuse half is the same surface again: it finds the depth the frame's half wrote. */
633
+ depthWriteEnabled: depthWrite && !diffuseAlone,
634
+ depthCompare: diffuseAlone ? 'equal' : DEPTH_COMPARE,
538
635
  /*
539
636
  * Baked in, where the other backend toggles it around the draw. Both read
540
637
  * `depthOffsetForLayer`, so a layer is worth the same depth on either one, and a pipeline
@@ -0,0 +1,74 @@
1
+ import type { SkinnedClothSetup } from '@driftengine/physics';
2
+ import { GpuClothParticles } from './clothTextures.ts';
3
+ /** One garment's solver on the device, and the particle textures it publishes into. */
4
+ export declare class GpuSkinnedCloth {
5
+ private readonly device;
6
+ /** The particles a bound mesh draws by: see `RendererApi.setCloth`. */
7
+ readonly particles: GpuClothParticles;
8
+ readonly count: number;
9
+ private readonly control;
10
+ private readonly packed;
11
+ private readonly kernels;
12
+ private readonly buffers;
13
+ private readonly state;
14
+ private readonly frameData;
15
+ private readonly stepSlots;
16
+ private readonly group;
17
+ private readonly outputs;
18
+ private readonly frameStaging;
19
+ private readonly stepStaging;
20
+ private readonly stepFloats;
21
+ private readonly stepWords;
22
+ /** Each batch's slot, by kind and by whether it opens a substep's iterations. */
23
+ private readonly batchSlot;
24
+ /** The air the steps drag toward: the set-up's until `setWind`, written into every step. */
25
+ private readonly wind;
26
+ private readonly groups;
27
+ private readonly substeps;
28
+ private readonly iterations;
29
+ private encoder;
30
+ private pass;
31
+ private slot;
32
+ /** Where the pose a step starts from and the one it moves toward sit in `pose`, in floats. */
33
+ private fromAt;
34
+ private toAt;
35
+ constructor(device: GPUDevice, setup: SkinnedClothSetup);
36
+ /**
37
+ * One frame: the rig's pose, `dt` of the caller's time in whole fixed steps, and the particles at
38
+ * the frame's `alpha` published for the draws that follow, as the particles of `frame`.
39
+ */
40
+ advance(globals: Float32Array, model: Float32Array, dt: number, frame: number): void;
41
+ /** The frame's sample of the scene's wind, for the steps to come. See `SkinnedCloth.setWind`. */
42
+ setWind(x: number, y: number, z: number): void;
43
+ /** Back to the skinned pose, settled; the next `advance` publishes it. */
44
+ reset(): void;
45
+ /**
46
+ * The particles where the last step left them, read back: for the parity check, which compares
47
+ * them with the CPU solver's. Not for a frame — it waits on the device.
48
+ */
49
+ read(): Promise<Float32Array>;
50
+ /** Its buffers; the particle textures are the renderer's to retire with the frame. */
51
+ dispose(): void;
52
+ private targetsChanged;
53
+ private rest;
54
+ private step;
55
+ /** Every batch of one kind, in colour order, each a dispatch over its range. */
56
+ private batches;
57
+ private dispatch;
58
+ private passFor;
59
+ /** Send what has been recorded: every slot it reads was written ahead of it on the queue. */
60
+ private flush;
61
+ /**
62
+ * A step's slot: its fraction, blend and alpha, the poses it reads, and — where `targets` is
63
+ * given — the share of the character's motion the cloth is carried by, as `carryParticles` takes
64
+ * it. Returns the slot's byte offset.
65
+ */
66
+ private takeSlot;
67
+ /** `carryParticles`' rotation, origin and move, into the step's slot; carry 0 where none. */
68
+ private writeCarry;
69
+ /** The pose's skin matrices — or the model, for a cloth with no rig — and its colliders. */
70
+ private writeFrameData;
71
+ private constants;
72
+ /** Each batch's range, twice — opening a substep's iterations and not — at a slot each. */
73
+ private writeBatches;
74
+ }