@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
@@ -21,6 +21,7 @@ const RIGID = 0;
21
21
  const SKINNED = 1;
22
22
  const DYNAMIC = 2;
23
23
  const INSTANCED = 3;
24
+ const CLOTH = 4;
24
25
 
25
26
  /** An instanced record's per-draw matrices are not read; this fills their slot. */
26
27
  const IDENTITY = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
@@ -37,6 +38,22 @@ export class MotionPass {
37
38
  /** A skinned record's two palettes, this frame's and last frame's, by record index. */
38
39
  private readonly paletteNow: (GPUTextureView | null)[] = [];
39
40
  private readonly paletteWas: (GPUTextureView | null)[] = [];
41
+ /** A cloth record's binding and its particles now and last frame, by record index. */
42
+ private readonly clothBinding: (GPUTextureView | null)[] = [];
43
+ private readonly clothNow: (GPUTextureView | null)[] = [];
44
+ private readonly clothWas: (GPUTextureView | null)[] = [];
45
+ private clothLayout: GPUBindGroupLayout | null = null;
46
+ private clothPipelineLayout: GPUPipelineLayout | null = null;
47
+ /** Keyed as `skinnedPipelines` is. */
48
+ private readonly clothPipelines = new Map<number, GPURenderPipeline>();
49
+ /**
50
+ * A bind group per particles now, particles then and binding. Weak at the top, by this frame's
51
+ * particles, so a character's groups go when its particles do; a steady garment settles on three.
52
+ */
53
+ private clothGroups = new WeakMap<
54
+ GPUTextureView,
55
+ Map<GPUTextureView, Map<GPUTextureView, GPUBindGroup>>
56
+ >();
40
57
  /** A rewritten record's last-frame rows, by record index. */
41
58
  private readonly previousRows: (GPUBuffer | null)[] = [];
42
59
  /** One pipeline per stride for rewritten meshes: current and previous rows at that stride. */
@@ -95,6 +112,28 @@ export class MotionPass {
95
112
  this.paletteWas[at] = previousPalette;
96
113
  }
97
114
 
115
+ /**
116
+ * A cloth-bound skinned draw: its skinned positions under both poses, each carried toward the
117
+ * cloth by its painted weight — this frame's `particles` and last frame's `previousParticles`.
118
+ */
119
+ recordCloth(
120
+ mesh: GpuMesh,
121
+ model: ArrayLike<number>,
122
+ previousModel: ArrayLike<number>,
123
+ palette: GPUTextureView,
124
+ previousPalette: GPUTextureView,
125
+ binding: GPUTextureView,
126
+ particles: GPUTextureView,
127
+ previousParticles: GPUTextureView,
128
+ ): void {
129
+ const at = this.take(mesh, model, previousModel, CLOTH);
130
+ this.paletteNow[at] = palette;
131
+ this.paletteWas[at] = previousPalette;
132
+ this.clothBinding[at] = binding;
133
+ this.clothNow[at] = particles;
134
+ this.clothWas[at] = previousParticles;
135
+ }
136
+
98
137
  /** A rewritten mesh: its vertices as they were, read from `previous`, under last frame's model. */
99
138
  recordDynamic(
100
139
  mesh: GpuMesh,
@@ -188,6 +227,18 @@ export class MotionPass {
188
227
  this.skinnedLayout = this.device.createPipelineLayout({
189
228
  bindGroupLayouts: [this.layout, this.paletteLayout],
190
229
  });
230
+ /* The binding and the two particle textures, read with `textureLoad` as the palettes are. */
231
+ this.clothLayout = this.device.createBindGroupLayout({
232
+ label: 'recon.motion.cloth',
233
+ entries: [0, 1, 2].map((binding) => ({
234
+ binding,
235
+ visibility: 0x1,
236
+ texture: { sampleType: 'unfilterable-float' as const },
237
+ })),
238
+ });
239
+ this.clothPipelineLayout = this.device.createPipelineLayout({
240
+ bindGroupLayouts: [this.layout, this.paletteLayout, this.clothLayout],
241
+ });
191
242
  }
192
243
 
193
244
  /**
@@ -198,20 +249,38 @@ export class MotionPass {
198
249
  */
199
250
  private skinnedPipelineFor(
200
251
  stride: number,
201
- offsets: { readonly joints: number; readonly weights: number },
252
+ offsets: {
253
+ readonly joints: number;
254
+ readonly weights: number;
255
+ readonly joints2: number;
256
+ readonly weights2: number;
257
+ },
258
+ cloth = false,
202
259
  ): GPURenderPipeline | null {
203
- const key = (stride * 4096 + offsets.joints) * 4096 + offsets.weights;
204
- const held = this.skinnedPipelines.get(key);
260
+ /* A rig of eight takes the stage that sums the second four as well. See motion.wgsl.ts. */
261
+ const eight = offsets.joints2 >= 0 && offsets.weights2 >= 0;
262
+ /*
263
+ * Five byte counts, each under 256 because a vertex is at most 172 bytes, as five base-256
264
+ * digits: exact below 2^40, so two layouts can never share a key.
265
+ */
266
+ const key =
267
+ (((stride * 256 + offsets.joints) * 256 + offsets.weights) * 256 + offsets.joints2 + 1) *
268
+ 256 +
269
+ offsets.weights2 +
270
+ 1;
271
+ const pipelines = cloth ? this.clothPipelines : this.skinnedPipelines;
272
+ const held = pipelines.get(key);
205
273
  if (held !== undefined) return held;
206
274
  const module = this.module;
207
- const layout = this.skinnedLayout;
275
+ const layout = cloth ? this.clothPipelineLayout : this.skinnedLayout;
208
276
  if (module === null || layout === null) return null;
277
+ const stage = cloth ? 'Cloth' : 'Skinned';
209
278
  const pipeline = this.device.createRenderPipeline({
210
- label: `recon.motion.skinned.${String(stride)}`,
279
+ label: `recon.motion.${cloth ? 'cloth' : 'skinned'}.${String(stride)}`,
211
280
  layout,
212
281
  vertex: {
213
282
  module,
214
- entryPoint: 'motionSkinnedVert',
283
+ entryPoint: eight ? `motion${stage}EightVert` : `motion${stage}Vert`,
215
284
  buffers: [
216
285
  {
217
286
  arrayStride: stride,
@@ -219,6 +288,12 @@ export class MotionPass {
219
288
  { shaderLocation: 0, offset: 0, format: 'float32x3' },
220
289
  { shaderLocation: 11, offset: offsets.joints, format: 'float32x4' },
221
290
  { shaderLocation: 12, offset: offsets.weights, format: 'float32x4' },
291
+ ...(eight
292
+ ? ([
293
+ { shaderLocation: 14, offset: offsets.joints2, format: 'float32x4' },
294
+ { shaderLocation: 15, offset: offsets.weights2, format: 'float32x4' },
295
+ ] as const)
296
+ : []),
222
297
  ],
223
298
  },
224
299
  ],
@@ -231,7 +306,7 @@ export class MotionPass {
231
306
  depthCompare: DEPTH_COMPARE_EQUAL,
232
307
  },
233
308
  });
234
- this.skinnedPipelines.set(key, pipeline);
309
+ pipelines.set(key, pipeline);
235
310
  return pipeline;
236
311
  }
237
312
 
@@ -342,6 +417,40 @@ export class MotionPass {
342
417
  return group;
343
418
  }
344
419
 
420
+ /** The bind group holding a cloth's binding and its two particle textures, built on first sight. */
421
+ private clothGroup(
422
+ binding: GPUTextureView,
423
+ now: GPUTextureView,
424
+ was: GPUTextureView,
425
+ ): GPUBindGroup | null {
426
+ const layout = this.clothLayout;
427
+ if (layout === null) return null;
428
+ let byWas = this.clothGroups.get(now);
429
+ if (byWas === undefined) {
430
+ byWas = new Map();
431
+ this.clothGroups.set(now, byWas);
432
+ }
433
+ let byBinding = byWas.get(was);
434
+ if (byBinding === undefined) {
435
+ byBinding = new Map();
436
+ byWas.set(was, byBinding);
437
+ }
438
+ let group = byBinding.get(binding);
439
+ if (group === undefined) {
440
+ group = this.device.createBindGroup({
441
+ label: 'recon.motion.cloth',
442
+ layout,
443
+ entries: [
444
+ { binding: 0, resource: binding },
445
+ { binding: 1, resource: now },
446
+ { binding: 2, resource: was },
447
+ ],
448
+ });
449
+ byBinding.set(binding, group);
450
+ }
451
+ return group;
452
+ }
453
+
345
454
  /** The pipeline for one vertex stride, built on first sight of it. */
346
455
  private pipelineFor(stride: number): GPURenderPipeline | null {
347
456
  const held = this.pipelines.get(stride);
@@ -497,14 +606,23 @@ export class MotionPass {
497
606
  if (previous === null) continue;
498
607
  pipeline = this.dynamicPipelineFor(mesh.vertexStride);
499
608
  pass.setVertexBuffer(1, previous);
500
- } else if (kind === SKINNED) {
609
+ } else if (kind === SKINNED || kind === CLOTH) {
501
610
  const offsets = mesh.skinOffsets;
502
611
  const now = this.paletteNow[i] ?? null;
503
612
  const was = this.paletteWas[i] ?? null;
504
613
  if (offsets === null || now === null || was === null) continue;
505
- pipeline = this.skinnedPipelineFor(mesh.vertexStride, offsets);
614
+ pipeline = this.skinnedPipelineFor(mesh.vertexStride, offsets, kind === CLOTH);
506
615
  const palettes = this.paletteGroup(now, was);
507
616
  if (pipeline === null || palettes === null) continue;
617
+ if (kind === CLOTH) {
618
+ const binding = this.clothBinding[i] ?? null;
619
+ const particles = this.clothNow[i] ?? null;
620
+ const previous = this.clothWas[i] ?? null;
621
+ if (binding === null || particles === null || previous === null) continue;
622
+ const cloth = this.clothGroup(binding, particles, previous);
623
+ if (cloth === null) continue;
624
+ pass.setBindGroup(2, cloth);
625
+ }
508
626
  pass.setBindGroup(1, palettes);
509
627
  } else {
510
628
  pipeline = this.pipelineFor(mesh.vertexStride);
@@ -526,6 +644,7 @@ export class MotionPass {
526
644
 
527
645
  dispose(): void {
528
646
  this.paletteGroups.clear();
647
+ this.clothGroups = new WeakMap();
529
648
  this.frameBuffer?.destroy();
530
649
  this.drawBuffer?.destroy();
531
650
  this.frameBuffer = null;
@@ -365,8 +365,10 @@ export function postPipelineTargets(
365
365
  key: string,
366
366
  fragment: string,
367
367
  targets: GPUColorTargetState[],
368
+ /** For a pass drawn into the frame's own multisampled colour, which must match its count. */
369
+ sampleCount = 1,
368
370
  ): GPURenderPipeline {
369
- return cache.get(key, () => describePost(device, layout, key, fragment, targets));
371
+ return cache.get(key, () => describePost(device, layout, key, fragment, targets, sampleCount));
370
372
  }
371
373
 
372
374
  function describePost(
@@ -375,8 +377,10 @@ function describePost(
375
377
  key: string,
376
378
  fragment: string,
377
379
  targets: GPUColorTargetState[],
380
+ sampleCount = 1,
378
381
  ): GPURenderPipelineDescriptor {
379
382
  return {
383
+ ...(sampleCount > 1 ? { multisample: { count: sampleCount } } : {}),
380
384
  label: key,
381
385
  layout: device.createPipelineLayout({ bindGroupLayouts: [layout] }),
382
386
  vertex: {