@driftengine/core 4.8.2 → 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 (259) hide show
  1. package/CHANGELOG.json +127 -0
  2. package/README.md +1 -1
  3. package/dist/geometry/meshConcat.js +2 -0
  4. package/dist/index.d.ts +11 -4
  5. package/dist/index.js +22 -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/materialChanges.d.ts +7 -2
  11. package/dist/render/backend/materialChanges.js +8 -3
  12. package/dist/render/backend/select.js +8 -0
  13. package/dist/render/backend/webgl2/clothTextures.d.ts +27 -0
  14. package/dist/render/backend/webgl2/clothTextures.js +93 -0
  15. package/dist/render/backend/webgl2/renderer.d.ts +159 -3
  16. package/dist/render/backend/webgl2/renderer.js +662 -80
  17. package/dist/render/backend/webgl2/skinScatter.d.ts +50 -0
  18. package/dist/render/backend/webgl2/skinScatter.js +256 -0
  19. package/dist/render/backend/webgpu/buffers.d.ts +25 -11
  20. package/dist/render/backend/webgpu/buffers.js +98 -49
  21. package/dist/render/backend/webgpu/causticsPass.js +2 -1
  22. package/dist/render/backend/webgpu/clothSolvePack.d.ts +27 -0
  23. package/dist/render/backend/webgpu/clothSolvePack.js +129 -0
  24. package/dist/render/backend/webgpu/clothTextures.d.ts +68 -0
  25. package/dist/render/backend/webgpu/clothTextures.js +145 -0
  26. package/dist/render/backend/webgpu/compressedUpload.d.ts +18 -0
  27. package/dist/render/backend/webgpu/compressedUpload.js +38 -0
  28. package/dist/render/backend/webgpu/computeHost.d.ts +21 -0
  29. package/dist/render/backend/webgpu/computeHost.js +5 -0
  30. package/dist/render/backend/webgpu/depthPass.d.ts +29 -9
  31. package/dist/render/backend/webgpu/depthPass.js +43 -12
  32. package/dist/render/backend/webgpu/drawCommand.js +6 -2
  33. package/dist/render/backend/webgpu/filmPass.js +2 -1
  34. package/dist/render/backend/webgpu/flatPass.d.ts +43 -4
  35. package/dist/render/backend/webgpu/flatPass.js +111 -13
  36. package/dist/render/backend/webgpu/gpuSkinnedCloth.d.ts +74 -0
  37. package/dist/render/backend/webgpu/gpuSkinnedCloth.js +452 -0
  38. package/dist/render/backend/webgpu/linePass.js +2 -1
  39. package/dist/render/backend/webgpu/motionPass.d.ts +20 -0
  40. package/dist/render/backend/webgpu/motionPass.js +106 -9
  41. package/dist/render/backend/webgpu/panelPass.js +2 -1
  42. package/dist/render/backend/webgpu/particlePass.js +2 -1
  43. package/dist/render/backend/webgpu/plumePass.js +2 -1
  44. package/dist/render/backend/webgpu/postPass.d.ts +15 -3
  45. package/dist/render/backend/webgpu/postPass.js +25 -8
  46. package/dist/render/backend/webgpu/renderer.d.ts +123 -6
  47. package/dist/render/backend/webgpu/renderer.js +534 -58
  48. package/dist/render/backend/webgpu/sdfTextPass.js +2 -1
  49. package/dist/render/backend/webgpu/shaders/clothSolve.wgsl.d.ts +33 -0
  50. package/dist/render/backend/webgpu/shaders/clothSolve.wgsl.js +469 -0
  51. package/dist/render/backend/webgpu/skinScatterPass.d.ts +51 -0
  52. package/dist/render/backend/webgpu/skinScatterPass.js +253 -0
  53. package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +4 -1
  54. package/dist/render/backend/webgpu/surfaceTexturePass.js +37 -12
  55. package/dist/render/backend/webgpu/textPass.js +2 -1
  56. package/dist/render/backend/webgpu/waterPass.js +2 -1
  57. package/dist/render/backend/webgpu/windStreakPass.js +2 -1
  58. package/dist/render/boltBatch.js +2 -1
  59. package/dist/render/causticsRenderer.js +2 -1
  60. package/dist/render/clothBindingData.d.ts +41 -0
  61. package/dist/render/clothBindingData.js +72 -0
  62. package/dist/render/clothPlacement.d.ts +25 -0
  63. package/dist/render/clothPlacement.js +85 -0
  64. package/dist/render/compressedSource.d.ts +66 -0
  65. package/dist/render/compressedSource.js +138 -0
  66. package/dist/render/cutoutCaster.d.ts +5 -1
  67. package/dist/render/cutoutCaster.js +6 -0
  68. package/dist/render/cutoutDither.d.ts +51 -0
  69. package/dist/render/cutoutDither.js +90 -0
  70. package/dist/render/decalPass.js +2 -1
  71. package/dist/render/eyeRefraction.d.ts +35 -0
  72. package/dist/render/eyeRefraction.js +40 -0
  73. package/dist/render/glCompressed.d.ts +27 -0
  74. package/dist/render/glCompressed.js +53 -0
  75. package/dist/render/globalMediumPass.js +3 -2
  76. package/dist/render/hairLobes.d.ts +70 -0
  77. package/dist/render/hairLobes.js +120 -0
  78. package/dist/render/lightBudget.d.ts +22 -0
  79. package/dist/render/lightBudget.js +22 -0
  80. package/dist/render/lineBatch.js +5 -1
  81. package/dist/render/mesh.d.ts +7 -0
  82. package/dist/render/mesh.js +24 -0
  83. package/dist/render/oitPass.js +2 -1
  84. package/dist/render/particleBatch.js +3 -2
  85. package/dist/render/particlePool.d.ts +6 -2
  86. package/dist/render/plumeRenderer.js +3 -2
  87. package/dist/render/recon/motionVectors.d.ts +4 -2
  88. package/dist/render/recon/motionVectors.js +6 -3
  89. package/dist/render/renderQuality.d.ts +29 -2
  90. package/dist/render/renderQuality.js +5 -0
  91. package/dist/render/rendererHarness.js +4 -0
  92. package/dist/render/sceneCoverage.d.ts +54 -0
  93. package/dist/render/sceneCoverage.js +72 -0
  94. package/dist/render/sceneTarget.d.ts +12 -0
  95. package/dist/render/sceneTarget.js +14 -0
  96. package/dist/render/sdfTextRenderer.js +2 -1
  97. package/dist/render/shaders/clothBinding.d.ts +22 -0
  98. package/dist/render/shaders/clothBinding.js +80 -0
  99. package/dist/render/shaders/depth.js +45 -8
  100. package/dist/render/shaders/flat/anisotropic.d.ts +15 -0
  101. package/dist/render/shaders/flat/anisotropic.js +68 -0
  102. package/dist/render/shaders/flat/eye.d.ts +1 -0
  103. package/dist/render/shaders/flat/eye.js +81 -0
  104. package/dist/render/shaders/flat/hair.d.ts +1 -0
  105. package/dist/render/shaders/flat/hair.js +101 -0
  106. package/dist/render/shaders/flat/index.js +42 -3
  107. package/dist/render/shaders/flat/main.d.ts +1 -1
  108. package/dist/render/shaders/flat/main.js +113 -17
  109. package/dist/render/shaders/flat/models.d.ts +14 -0
  110. package/dist/render/shaders/flat/models.js +273 -0
  111. package/dist/render/shaders/flat/preamble.js +26 -24
  112. package/dist/render/shaders/flat/skin.d.ts +1 -0
  113. package/dist/render/shaders/flat/skin.js +114 -0
  114. package/dist/render/shaders/generated/depth.wgsl.d.ts +66 -24
  115. package/dist/render/shaders/generated/depth.wgsl.js +66 -24
  116. package/dist/render/shaders/generated/flat.wgsl.d.ts +1815 -1704
  117. package/dist/render/shaders/generated/flat.wgsl.js +1853 -1742
  118. package/dist/render/shaders/generated/line.wgsl.d.ts +1 -1
  119. package/dist/render/shaders/generated/line.wgsl.js +1 -1
  120. package/dist/render/shaders/generated/particle.wgsl.d.ts +3 -3
  121. package/dist/render/shaders/generated/particle.wgsl.js +3 -3
  122. package/dist/render/shaders/generated/rush.wgsl.d.ts +1 -1
  123. package/dist/render/shaders/generated/rush.wgsl.js +1 -1
  124. package/dist/render/shaders/generated/sdfText.wgsl.d.ts +1 -1
  125. package/dist/render/shaders/generated/sdfText.wgsl.js +1 -1
  126. package/dist/render/shaders/generated/skinBlur.wgsl.d.ts +48 -0
  127. package/dist/render/shaders/generated/skinBlur.wgsl.js +54 -0
  128. package/dist/render/shaders/generated/temporalResolve.wgsl.d.ts +1 -1
  129. package/dist/render/shaders/generated/temporalResolve.wgsl.js +1 -1
  130. package/dist/render/shaders/line.d.ts +1 -1
  131. package/dist/render/shaders/outputTransform.d.ts +14 -1
  132. package/dist/render/shaders/outputTransform.js +23 -1
  133. package/dist/render/shaders/particle.d.ts +3 -3
  134. package/dist/render/shaders/recon/motion.wgsl.d.ts +1 -1
  135. package/dist/render/shaders/recon/motion.wgsl.js +102 -0
  136. package/dist/render/shaders/recon/resolve.wgsl.js +15 -1
  137. package/dist/render/shaders/rush.js +13 -2
  138. package/dist/render/shaders/sdfText.d.ts +1 -1
  139. package/dist/render/shaders/skinBlur.d.ts +1 -0
  140. package/dist/render/shaders/skinBlur.js +103 -0
  141. package/dist/render/shaders/skinning.d.ts +3 -1
  142. package/dist/render/shaders/skinning.js +31 -4
  143. package/dist/render/shaders/temporalResolve.js +12 -5
  144. package/dist/render/shadowCasters.d.ts +13 -1
  145. package/dist/render/skinBlur.d.ts +41 -0
  146. package/dist/render/skinBlur.js +49 -0
  147. package/dist/render/skinScatter.d.ts +67 -0
  148. package/dist/render/skinScatter.js +80 -0
  149. package/dist/render/skinnedClothRun.d.ts +26 -0
  150. package/dist/render/skinnedClothRun.js +84 -0
  151. package/dist/render/ssrPass.js +2 -1
  152. package/dist/render/surfaceModel.d.ts +129 -0
  153. package/dist/render/surfaceModel.js +152 -0
  154. package/dist/render/surfaceTexture.d.ts +55 -4
  155. package/dist/render/surfaceTexture.js +60 -46
  156. package/dist/render/textRenderer.js +2 -1
  157. package/dist/render/vertexDefaults.js +8 -0
  158. package/dist/render/waterRenderer.js +2 -1
  159. package/dist/render/windStreakRenderer.js +2 -1
  160. package/package.json +6 -6
  161. package/src/geometry/meshConcat.ts +2 -0
  162. package/src/index.ts +53 -1
  163. package/src/math/scalar.ts +1 -1
  164. package/src/render/anisotropicLobe.ts +41 -0
  165. package/src/render/backend/api.ts +52 -3
  166. package/src/render/backend/materialChanges.ts +8 -3
  167. package/src/render/backend/select.ts +8 -0
  168. package/src/render/backend/webgl2/clothTextures.ts +120 -0
  169. package/src/render/backend/webgl2/renderer.ts +750 -80
  170. package/src/render/backend/webgl2/skinScatter.ts +309 -0
  171. package/src/render/backend/webgpu/buffers.ts +137 -63
  172. package/src/render/backend/webgpu/causticsPass.ts +2 -1
  173. package/src/render/backend/webgpu/clothSolvePack.ts +161 -0
  174. package/src/render/backend/webgpu/clothTextures.ts +194 -0
  175. package/src/render/backend/webgpu/compressedUpload.ts +65 -0
  176. package/src/render/backend/webgpu/computeHost.ts +25 -0
  177. package/src/render/backend/webgpu/depthPass.ts +43 -10
  178. package/src/render/backend/webgpu/drawCommand.ts +6 -2
  179. package/src/render/backend/webgpu/filmPass.ts +2 -1
  180. package/src/render/backend/webgpu/flatPass.ts +147 -8
  181. package/src/render/backend/webgpu/gpuSkinnedCloth.ts +502 -0
  182. package/src/render/backend/webgpu/linePass.ts +2 -1
  183. package/src/render/backend/webgpu/motionPass.ts +128 -9
  184. package/src/render/backend/webgpu/panelPass.ts +2 -1
  185. package/src/render/backend/webgpu/particlePass.ts +2 -1
  186. package/src/render/backend/webgpu/plumePass.ts +2 -1
  187. package/src/render/backend/webgpu/postPass.ts +25 -6
  188. package/src/render/backend/webgpu/renderer.ts +701 -52
  189. package/src/render/backend/webgpu/sdfTextPass.ts +2 -1
  190. package/src/render/backend/webgpu/shaders/clothSolve.wgsl.ts +470 -0
  191. package/src/render/backend/webgpu/skinScatterPass.ts +309 -0
  192. package/src/render/backend/webgpu/surfaceTexturePass.ts +42 -12
  193. package/src/render/backend/webgpu/textPass.ts +2 -1
  194. package/src/render/backend/webgpu/waterPass.ts +2 -1
  195. package/src/render/backend/webgpu/windStreakPass.ts +2 -1
  196. package/src/render/boltBatch.ts +2 -1
  197. package/src/render/causticsRenderer.ts +2 -1
  198. package/src/render/clothBindingData.ts +89 -0
  199. package/src/render/clothPlacement.ts +114 -0
  200. package/src/render/compressedSource.ts +198 -0
  201. package/src/render/cutoutCaster.ts +20 -2
  202. package/src/render/cutoutDither.ts +99 -0
  203. package/src/render/decalPass.ts +2 -1
  204. package/src/render/eyeRefraction.ts +72 -0
  205. package/src/render/glCompressed.ts +86 -0
  206. package/src/render/globalMediumPass.ts +3 -2
  207. package/src/render/hairLobes.ts +188 -0
  208. package/src/render/lightBudget.ts +25 -0
  209. package/src/render/lineBatch.ts +3 -1
  210. package/src/render/mesh.ts +23 -0
  211. package/src/render/oitPass.ts +2 -1
  212. package/src/render/particleBatch.ts +3 -2
  213. package/src/render/particlePool.ts +6 -2
  214. package/src/render/plumeRenderer.ts +3 -2
  215. package/src/render/recon/motionVectors.ts +6 -3
  216. package/src/render/renderQuality.ts +37 -2
  217. package/src/render/rendererHarness.ts +4 -0
  218. package/src/render/sceneCoverage.ts +78 -0
  219. package/src/render/sceneTarget.ts +21 -0
  220. package/src/render/sdfTextRenderer.ts +2 -1
  221. package/src/render/shaders/clothBinding.ts +81 -0
  222. package/src/render/shaders/depth.ts +45 -8
  223. package/src/render/shaders/flat/anisotropic.ts +68 -0
  224. package/src/render/shaders/flat/eye.ts +82 -0
  225. package/src/render/shaders/flat/hair.ts +102 -0
  226. package/src/render/shaders/flat/index.ts +42 -3
  227. package/src/render/shaders/flat/main.ts +113 -17
  228. package/src/render/shaders/flat/models.ts +286 -0
  229. package/src/render/shaders/flat/preamble.ts +26 -24
  230. package/src/render/shaders/flat/skin.ts +116 -0
  231. package/src/render/shaders/generated/depth.wgsl.ts +66 -24
  232. package/src/render/shaders/generated/flat.wgsl.ts +1853 -1742
  233. package/src/render/shaders/generated/line.wgsl.ts +1 -1
  234. package/src/render/shaders/generated/particle.wgsl.ts +3 -3
  235. package/src/render/shaders/generated/rush.wgsl.ts +1 -1
  236. package/src/render/shaders/generated/sdfText.wgsl.ts +1 -1
  237. package/src/render/shaders/generated/skinBlur.wgsl.ts +56 -0
  238. package/src/render/shaders/generated/temporalResolve.wgsl.ts +1 -1
  239. package/src/render/shaders/outputTransform.ts +24 -1
  240. package/src/render/shaders/recon/motion.wgsl.ts +102 -0
  241. package/src/render/shaders/recon/resolve.wgsl.ts +15 -1
  242. package/src/render/shaders/rush.ts +13 -2
  243. package/src/render/shaders/skinBlur.ts +105 -0
  244. package/src/render/shaders/skinning.ts +31 -4
  245. package/src/render/shaders/temporalResolve.ts +12 -5
  246. package/src/render/shadowCasters.ts +13 -0
  247. package/src/render/skinBlur.ts +53 -0
  248. package/src/render/skinScatter.ts +92 -0
  249. package/src/render/skinnedClothRun.ts +128 -0
  250. package/src/render/ssrPass.ts +2 -1
  251. package/src/render/surfaceModel.ts +274 -0
  252. package/src/render/surfaceTexture.ts +134 -63
  253. package/src/render/textRenderer.ts +2 -1
  254. package/src/render/vertexDefaults.ts +8 -0
  255. package/src/render/waterRenderer.ts +2 -1
  256. package/src/render/windStreakRenderer.ts +2 -1
  257. package/dist/math/exact.d.ts +0 -76
  258. package/dist/math/exact.js +0 -327
  259. package/src/math/exact.ts +0 -340
@@ -1,3 +1,6 @@
1
+ import { SURFACE_MODEL_SWITCH } from '../../surfaceModel.ts';
2
+ import type { SurfaceModelKind } from '../../surfaceModel.ts';
3
+ import type { SkinHalf } from '../../shaders/flat/models.ts';
1
4
  import { DEPTH_COMPARE, DEPTH_FORMAT, depthOffsetForLayer } from '../../depthConvention.ts';
2
5
  import {
3
6
  FLAT_BINDINGS,
@@ -6,7 +9,9 @@ import {
6
9
  } from '../../shaders/generated/flat.wgsl.ts';
7
10
  import { vertexBufferLayouts } from './buffers.ts';
8
11
  import type { LitSwitch, PipelineCache } from './pipelineCache.ts';
12
+ import type { ClothViews } from './clothTextures.ts';
9
13
  import { shaderModule } from './shaderModules.ts';
14
+ import { SCENE_ALPHA_COVERS } from '../../sceneCoverage.ts';
10
15
 
11
16
  /** The material maps the flat pass reads: `2d-array` colour, filtered, not shadow maps. */
12
17
  const SURFACE_MAPS: ReadonlySet<string> = new Set([
@@ -14,6 +19,7 @@ const SURFACE_MAPS: ReadonlySet<string> = new Set([
14
19
  'uNormalMap',
15
20
  'uOrmMap',
16
21
  'uEmissiveMap',
22
+ 'uModelMap',
17
23
  ]);
18
24
 
19
25
  /**
@@ -145,6 +151,38 @@ export function flatVertexBindings(
145
151
  }
146
152
 
147
153
  const PLAIN_VERTEX = flatVertexBindings(false);
154
+
155
+ /**
156
+ * A vertex stage's constants, keyed by each override's **id** as the fragment's are: `SKIN_EIGHT` in
157
+ * a skinned stage, nothing in any other. Every override a stage declares is set, and one this does
158
+ * not know is refused here rather than defaulted. Shared with the shadow and glass-tint casters,
159
+ * whose skinned stages declare the same switch.
160
+ */
161
+ export function vertexConstants(
162
+ bindings: StageBindings,
163
+ skinEight: boolean,
164
+ cloth = false,
165
+ ): Record<string, number> {
166
+ const constants: Record<string, number> = {};
167
+ for (const [name, id] of Object.entries(bindings.overrides ?? {})) {
168
+ if (name === 'SKIN_EIGHT') constants[String(id)] = skinEight ? 1 : 0;
169
+ else if (name === 'CLOTH_BOUND') constants[String(id)] = cloth ? 1 : 0;
170
+ else throw new Error(`flatPass: a vertex stage declares a switch "${name}" nothing sets`);
171
+ }
172
+ return constants;
173
+ }
174
+ /** Where a skinned stage declares the cloth binding's three textures: binding, particles, rest. */
175
+ function clothBindings(skinned: boolean, morphed: boolean): [number, number, number] {
176
+ const textures = flatVertexBindings(skinned, morphed).textures;
177
+ const at = (name: string): number => {
178
+ const found = textures[name];
179
+ if (found === undefined)
180
+ throw new Error(`flatPass: the skinned vertex shader declares no ${name}`);
181
+ return found.texture;
182
+ };
183
+ return [at('uClothBinding'), at('uClothParticles'), at('uClothRest')];
184
+ }
185
+
148
186
  /*
149
187
  * **A variant may drop a field; it may never move one.**
150
188
  *
@@ -207,13 +245,33 @@ export function flatFragmentBindings(variant: FlatVariant): StageBindings {
207
245
  * "GLASS_SHADOWS" not found*, and the frame drew nothing. Every override the variant declares is
208
246
  * set, so a switch added to the shader and not to the cache is refused here rather than defaulted.
209
247
  */
210
- function flatFragmentConstants(variant: FlatVariant, cache: PipelineCache): Record<string, number> {
248
+ function flatFragmentConstants(
249
+ variant: FlatVariant,
250
+ cache: PipelineCache,
251
+ model: SurfaceModelKind | null,
252
+ skinPass: SkinHalf = 'whole',
253
+ ): Record<string, number> {
211
254
  const overrides = flatFragmentBindings(variant).overrides;
212
255
  if (overrides?.['GLASS_SHADOWS'] === undefined) {
213
256
  throw new Error(`flatPass: variant "${variant}" has no glass switch`);
214
257
  }
258
+ const modelSwitch = model === null ? null : SURFACE_MODEL_SWITCH[model];
215
259
  const constants: Record<string, number> = {};
216
260
  for (const [name, id] of Object.entries(overrides)) {
261
+ /* A model's switch is the pipeline's own, set from its key rather than from the cache. */
262
+ if (name.startsWith('MODEL_')) {
263
+ constants[String(id)] = name === modelSwitch ? 1 : 0;
264
+ continue;
265
+ }
266
+ /* Skin's two halves under the screen-space blur, set from the key as a model's switch is. */
267
+ if (name === 'SKIN_SCREEN' || name === 'SKIN_DIFFUSE') {
268
+ constants[String(id)] =
269
+ (name === 'SKIN_SCREEN' && skinPass === 'scene') ||
270
+ (name === 'SKIN_DIFFUSE' && skinPass === 'diffuse')
271
+ ? 1
272
+ : 0;
273
+ continue;
274
+ }
217
275
  if (!(name in cache.litSwitches)) {
218
276
  throw new Error(`flatPass: variant "${variant}" declares a switch "${name}" no cache sets`);
219
277
  }
@@ -394,6 +452,15 @@ export function createFlatBindGroupLayout(
394
452
  visibility: VISIBILITY_VERTEX,
395
453
  texture: { sampleType: 'unfilterable-float' },
396
454
  });
455
+ /* The cloth binding's three textures, declared by every skinned stage whether a draw sets a
456
+ cloth or not; see `clothBinding.ts`. */
457
+ for (const binding of clothBindings(skinned, morphed)) {
458
+ entries.push({
459
+ binding,
460
+ visibility: VISIBILITY_VERTEX,
461
+ texture: { sampleType: 'unfilterable-float' },
462
+ });
463
+ }
397
464
  }
398
465
 
399
466
  return device.createBindGroupLayout({
@@ -407,7 +474,7 @@ export function createFlatBindGroupLayout(
407
474
  *
408
475
  * `resolve` is asked for a view by the shader's own name for it, so a caller supplies the
409
476
  * shadow maps it has and a stand-in for the rest. **Every declared binding must be filled
410
- * even when the shader never samples it** — `uAlbedoEnabled` is zero for nearly all geometry
477
+ * even when the shader never samples it** — the albedo's flag is zero for nearly all geometry
411
478
  * and WebGPU still requires something there, which is why `renderer.ts` keeps an
412
479
  * `emptyTexture2D` for the same reason on the other side.
413
480
  */
@@ -422,6 +489,8 @@ export function createFlatBindGroup(
422
489
  palette: GPUTextureView | null = null,
423
490
  /** The delta view for a morphed bind group, or null for an unmorphed one. */
424
491
  deltas: GPUTextureView | null = null,
492
+ /** A skinned bind group's cloth views — the draw's, or the stand-in where it sets none. */
493
+ cloth: ClothViews | null = null,
425
494
  ): GPUBindGroup {
426
495
  const fragment = flatFragmentBindings(variant);
427
496
  const entries: GPUBindGroupEntry[] = [
@@ -457,6 +526,15 @@ export function createFlatBindGroup(
457
526
  throw new Error('flatPass: the skinned vertex shader declares no uJointPalette');
458
527
  }
459
528
  entries.push({ binding: binding.texture, resource: palette });
529
+ if (cloth === null) {
530
+ throw new Error(
531
+ 'flatPass: a skinned bind group needs cloth views, the stand-in at the least',
532
+ );
533
+ }
534
+ const [bindingAt, particlesAt, restAt] = clothBindings(true, deltas !== null);
535
+ entries.push({ binding: bindingAt, resource: cloth.binding });
536
+ entries.push({ binding: particlesAt, resource: cloth.particles });
537
+ entries.push({ binding: restAt, resource: cloth.rest });
460
538
  }
461
539
 
462
540
  return device.createBindGroup({
@@ -516,6 +594,22 @@ export function flatPipeline(
516
594
  oit: OitTarget = 'none',
517
595
  /** Culls nothing, for a surface seen from both faces. The key must carry it: `|2s`. */
518
596
  doubleSided = false,
597
+ /**
598
+ * Turns the fragment's alpha into the pixel's samples, for a dithered cutout in a multisampled
599
+ * frame with no temporal resolve. The key must carry it: `|a2c`. See `cutoutDither.ts`.
600
+ */
601
+ alphaToCoverage = false,
602
+ /**
603
+ * Whether a skinned pipeline reads the second four influences: the vertex stage's `SKIN_EIGHT`.
604
+ * The key must carry it: `|s8`. See `skinning.ts`.
605
+ */
606
+ skinEight = false,
607
+ /** Whether its vertex stage places vertices by a cloth binding. See `clothBinding.ts`. */
608
+ cloth = false,
609
+ /** Which shading model its fragment stage shades by, null the standard. The key must carry it. */
610
+ model: SurfaceModelKind | null = null,
611
+ /** Which half of a skin it draws. The key must carry it: `|ss` or `|sd`. See `SkinHalf`. */
612
+ skinPass: SkinHalf = 'whole',
519
613
  ): GPURenderPipeline {
520
614
  return cache.get(
521
615
  key,
@@ -535,6 +629,11 @@ export function flatPipeline(
535
629
  instanced,
536
630
  oit,
537
631
  doubleSided,
632
+ alphaToCoverage,
633
+ skinEight,
634
+ cloth,
635
+ model,
636
+ skinPass,
538
637
  ),
539
638
  true,
540
639
  );
@@ -561,11 +660,36 @@ export function flatPipelineAsync(
561
660
  skinned = false,
562
661
  /** Whether this pipeline reads morph deltas. See `FlatVertexOptions`. */
563
662
  morphed = false,
663
+ /** Whether the skinned stage reads the second four influences. See `flatPipeline`. */
664
+ skinEight = false,
665
+ /** Whether its vertex stage places vertices by a cloth binding. See `clothBinding.ts`. */
666
+ cloth = false,
667
+ /** Which shading model its fragment stage shades by. See `flatPipeline`. */
668
+ model: SurfaceModelKind | null = null,
564
669
  ): Promise<GPURenderPipeline> {
565
670
  return cache.getAsync(
566
671
  key,
567
672
  () =>
568
- flatDescriptor(cache, device, layout, variant, key, present, translucent, skinned, morphed),
673
+ flatDescriptor(
674
+ cache,
675
+ device,
676
+ layout,
677
+ variant,
678
+ key,
679
+ present,
680
+ translucent,
681
+ skinned,
682
+ morphed,
683
+ true,
684
+ 0,
685
+ false,
686
+ 'none',
687
+ false,
688
+ false,
689
+ skinEight,
690
+ cloth,
691
+ model,
692
+ ),
569
693
  true,
570
694
  );
571
695
  }
@@ -636,8 +760,15 @@ function flatDescriptor(
636
760
  oit: OitTarget = 'none',
637
761
  /** Culls nothing: a surface seen from both faces. */
638
762
  doubleSided = false,
763
+ alphaToCoverage = false,
764
+ skinEight = false,
765
+ /** Whether its vertex stage places vertices by a cloth binding. See `clothBinding.ts`. */
766
+ cloth = false,
767
+ model: SurfaceModelKind | null = null,
768
+ skinPass: SkinHalf = 'whole',
639
769
  ): GPURenderPipelineDescriptor {
640
770
  const offset = depthOffsetForLayer(depthLayer);
771
+ const diffuseAlone = skinPass === 'diffuse';
641
772
  return {
642
773
  label: key,
643
774
  layout: device.createPipelineLayout({ bindGroupLayouts: [layout] }),
@@ -653,6 +784,7 @@ function flatDescriptor(
653
784
  }),
654
785
  entryPoint: 'main',
655
786
  buffers: vertexBufferLayouts(present, instanced),
787
+ constants: vertexConstants(flatVertexBindings(skinned, morphed, instanced), skinEight, cloth),
656
788
  },
657
789
  fragment: {
658
790
  module: shaderModule(device, {
@@ -661,7 +793,7 @@ function flatDescriptor(
661
793
  }),
662
794
  entryPoint: 'main',
663
795
  /* Every variant declares it, so every lit pipeline may set it: see `PipelineCache`. */
664
- constants: flatFragmentConstants(variant, cache),
796
+ constants: flatFragmentConstants(variant, cache, model, skinPass),
665
797
  targets: [
666
798
  oitTarget(oit) ??
667
799
  (translucent === 'additive'
@@ -681,14 +813,20 @@ function flatDescriptor(
681
813
  dstFactor: 'one-minus-src-alpha',
682
814
  operation: 'add',
683
815
  },
684
- alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },
816
+ alpha: SCENE_ALPHA_COVERS,
685
817
  },
686
818
  }
687
819
  : { format: cache.format }),
688
820
  ],
689
821
  },
690
822
  primitive: { topology: 'triangle-list', cullMode: doubleSided ? 'none' : 'back' },
691
- multisample: { count: cache.sampleCount },
823
+ /* Coverage only where a sample count can carry it: WebGPU refuses it at one sample. */
824
+ multisample: {
825
+ count: cache.sampleCount,
826
+ ...(alphaToCoverage && cache.sampleCount > 1 && !diffuseAlone
827
+ ? { alphaToCoverageEnabled: true }
828
+ : {}),
829
+ },
692
830
  /*
693
831
  * `less`, matching the WebGL2 path's `LESS` rather than `LEQUAL`, and for the reason
694
832
  * `drawMesh` documents there: under `LEQUAL` two coplanar surfaces do not merely tie,
@@ -696,8 +834,9 @@ function flatDescriptor(
696
834
  */
697
835
  depthStencil: {
698
836
  format: DEPTH_FORMAT,
699
- depthWriteEnabled: depthWrite,
700
- depthCompare: DEPTH_COMPARE,
837
+ /* The diffuse half is the same surface again: it finds the depth the frame's half wrote. */
838
+ depthWriteEnabled: depthWrite && !diffuseAlone,
839
+ depthCompare: diffuseAlone ? 'equal' : DEPTH_COMPARE,
701
840
  /*
702
841
  * Baked in, where the other backend toggles it around the draw. Both read
703
842
  * `depthOffsetForLayer`, so a layer is worth the same depth on either one, and a pipeline