@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
@@ -10,8 +10,12 @@
10
10
  * replays them, which is what turns migrating twenty-three verbs into twenty-three call-site
11
11
  * edits rather than twenty-three implementations.
12
12
  */
13
- /** The most vertex buffers any verb on this backend binds is three. Four leaves a margin. */
14
- const VERTEX_BUFFER_SLOTS = 4;
13
+ /**
14
+ * WebGPU's guaranteed `maxVertexBuffers`, so no verb can outgrow it. The most any binds is five — a
15
+ * dynamic mesh's positions, normals, rows and constants, and an instanced batch's placements — and
16
+ * this said three, then four, while text and bolts already bound four.
17
+ */
18
+ const VERTEX_BUFFER_SLOTS = 8;
15
19
  function emptyCommand() {
16
20
  return {
17
21
  pipeline: null,
@@ -3,6 +3,7 @@ import { FILM_BINDINGS, FILM_FRAG_WGSL, FILM_VERT_WGSL, } from '../../shaders/ge
3
3
  import { vertexBufferLayouts } from './buffers.js';
4
4
  import { DEPTH_FORMAT } from './flatPass.js';
5
5
  import { shaderModule } from './shaderModules.js';
6
+ import { SCENE_ALPHA_KEEPS } from '../../sceneCoverage.js';
6
7
  /**
7
8
  * The film pass: a thin wet layer — an oil slick, a puddle — lying over the world.
8
9
  *
@@ -85,7 +86,7 @@ export function filmPipeline(cache, device, layout, key, present) {
85
86
  format: cache.format,
86
87
  blend: {
87
88
  color: { srcFactor: 'src-alpha', dstFactor: 'one-minus-src-alpha', operation: 'add' },
88
- alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },
89
+ alpha: SCENE_ALPHA_KEEPS,
89
90
  },
90
91
  },
91
92
  ],
@@ -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;
@@ -86,6 +96,11 @@ export declare const FLAT_VERT_FIELDS: {
86
96
  readonly size: 8;
87
97
  readonly type: "vec2";
88
98
  };
99
+ readonly uUvOffset: {
100
+ readonly offset: 152;
101
+ readonly size: 8;
102
+ readonly type: "vec2";
103
+ };
89
104
  readonly uModel: {
90
105
  readonly offset: 160;
91
106
  readonly size: 64;
@@ -147,7 +162,7 @@ export declare function createFlatBindGroupLayout(device: GPUDevice, variant: Fl
147
162
  *
148
163
  * `resolve` is asked for a view by the shader's own name for it, so a caller supplies the
149
164
  * shadow maps it has and a stand-in for the rest. **Every declared binding must be filled
150
- * 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
151
166
  * and WebGPU still requires something there, which is why `renderer.ts` keeps an
152
167
  * `emptyTexture2D` for the same reason on the other side.
153
168
  */
@@ -158,7 +173,9 @@ export declare function createFlatBindGroup(device: GPUDevice, layout: GPUBindGr
158
173
  /** The palette view for a skinned bind group, or null for an unskinned one. */
159
174
  palette?: GPUTextureView | null,
160
175
  /** The delta view for a morphed bind group, or null for an unmorphed one. */
161
- 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;
162
179
  /**
163
180
  * The pipeline, cached by the state that distinguishes it.
164
181
  *
@@ -201,7 +218,23 @@ instanced?: boolean,
201
218
  /** Which order-independent buffer this pipeline writes, if any. The key must carry it. */
202
219
  oit?: OitTarget,
203
220
  /** Culls nothing, for a surface seen from both faces. The key must carry it: `|2s`. */
204
- 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;
205
238
  /**
206
239
  * The same pipeline, compiled off the main thread.
207
240
  *
@@ -215,6 +248,12 @@ export declare function flatPipelineAsync(cache: PipelineCache, device: GPUDevic
215
248
  /** Whether this pipeline reads a joint palette. See `FlatVertexOptions`. */
216
249
  skinned?: boolean,
217
250
  /** Whether this pipeline reads morph deltas. See `FlatVertexOptions`. */
218
- 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>;
219
258
  /** Which of the two order-independent buffers a pipeline writes, or neither. */
220
259
  export type OitTarget = 'none' | 'accum' | 'reveal';
@@ -1,13 +1,16 @@
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';
4
5
  import { shaderModule } from './shaderModules.js';
6
+ import { SCENE_ALPHA_COVERS } from '../../sceneCoverage.js';
5
7
  /** The material maps the flat pass reads: `2d-array` colour, filtered, not shadow maps. */
6
8
  const SURFACE_MAPS = new Set([
7
9
  'uAlbedo',
8
10
  'uNormalMap',
9
11
  'uOrmMap',
10
12
  'uEmissiveMap',
13
+ 'uModelMap',
11
14
  ]);
12
15
  /**
13
16
  * The key for a set of flags.
@@ -67,6 +70,35 @@ export function flatVertexBindings(skinned, morphed = false, instanced = false)
67
70
  return found;
68
71
  }
69
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
+ }
70
102
  /*
71
103
  * **A variant may drop a field; it may never move one.**
72
104
  *
@@ -123,13 +155,28 @@ export function flatFragmentBindings(variant) {
123
155
  * "GLASS_SHADOWS" not found*, and the frame drew nothing. Every override the variant declares is
124
156
  * set, so a switch added to the shader and not to the cache is refused here rather than defaulted.
125
157
  */
126
- function flatFragmentConstants(variant, cache) {
158
+ function flatFragmentConstants(variant, cache, model, skinPass = 'whole') {
127
159
  const overrides = flatFragmentBindings(variant).overrides;
128
160
  if (overrides?.['GLASS_SHADOWS'] === undefined) {
129
161
  throw new Error(`flatPass: variant "${variant}" has no glass switch`);
130
162
  }
163
+ const modelSwitch = model === null ? null : SURFACE_MODEL_SWITCH[model];
131
164
  const constants = {};
132
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
+ }
133
180
  if (!(name in cache.litSwitches)) {
134
181
  throw new Error(`flatPass: variant "${variant}" declares a switch "${name}" no cache sets`);
135
182
  }
@@ -297,6 +344,15 @@ export function createFlatBindGroupLayout(device, variant, skinned = false, morp
297
344
  visibility: VISIBILITY_VERTEX,
298
345
  texture: { sampleType: 'unfilterable-float' },
299
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
+ }
300
356
  }
301
357
  return device.createBindGroupLayout({
302
358
  label: `flat.layout:${variant}|${flatVertexKey(skinned, morphed)}`,
@@ -308,7 +364,7 @@ export function createFlatBindGroupLayout(device, variant, skinned = false, morp
308
364
  *
309
365
  * `resolve` is asked for a view by the shader's own name for it, so a caller supplies the
310
366
  * shadow maps it has and a stand-in for the rest. **Every declared binding must be filled
311
- * 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
312
368
  * and WebGPU still requires something there, which is why `renderer.ts` keeps an
313
369
  * `emptyTexture2D` for the same reason on the other side.
314
370
  */
@@ -316,7 +372,9 @@ export function createFlatBindGroup(device, layout, variant, perDraw, perFrame,
316
372
  /** The palette view for a skinned bind group, or null for an unskinned one. */
317
373
  palette = null,
318
374
  /** The delta view for a morphed bind group, or null for an unmorphed one. */
319
- 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) {
320
378
  const fragment = flatFragmentBindings(variant);
321
379
  const entries = [
322
380
  {
@@ -350,6 +408,13 @@ deltas = null) {
350
408
  throw new Error('flatPass: the skinned vertex shader declares no uJointPalette');
351
409
  }
352
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 });
353
418
  }
354
419
  return device.createBindGroup({
355
420
  label: `flat.bindGroup:${variant}|${flatVertexKey(palette !== null, deltas !== null)}`,
@@ -399,8 +464,24 @@ instanced = false,
399
464
  /** Which order-independent buffer this pipeline writes, if any. The key must carry it. */
400
465
  oit = 'none',
401
466
  /** Culls nothing, for a surface seen from both faces. The key must carry it: `|2s`. */
402
- doubleSided = false) {
403
- 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);
404
485
  }
405
486
  /**
406
487
  * The same pipeline, compiled off the main thread.
@@ -415,8 +496,14 @@ export function flatPipelineAsync(cache, device, layout, variant, key, present,
415
496
  /** Whether this pipeline reads a joint palette. See `FlatVertexOptions`. */
416
497
  skinned = false,
417
498
  /** Whether this pipeline reads morph deltas. See `FlatVertexOptions`. */
418
- morphed = false) {
419
- 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);
420
507
  }
421
508
  /**
422
509
  * The colour target for an order-independent pass, or null where this is an ordinary draw.
@@ -472,8 +559,11 @@ instanced = false,
472
559
  */
473
560
  oit = 'none',
474
561
  /** Culls nothing: a surface seen from both faces. */
475
- 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') {
476
565
  const offset = depthOffsetForLayer(depthLayer);
566
+ const diffuseAlone = skinPass === 'diffuse';
477
567
  return {
478
568
  label: key,
479
569
  layout: device.createPipelineLayout({ bindGroupLayouts: [layout] }),
@@ -489,6 +579,7 @@ doubleSided = false) {
489
579
  }),
490
580
  entryPoint: 'main',
491
581
  buffers: vertexBufferLayouts(present, instanced),
582
+ constants: vertexConstants(flatVertexBindings(skinned, morphed, instanced), skinEight, cloth),
492
583
  },
493
584
  fragment: {
494
585
  module: shaderModule(device, {
@@ -497,7 +588,7 @@ doubleSided = false) {
497
588
  }),
498
589
  entryPoint: 'main',
499
590
  /* Every variant declares it, so every lit pipeline may set it: see `PipelineCache`. */
500
- constants: flatFragmentConstants(variant, cache),
591
+ constants: flatFragmentConstants(variant, cache, model, skinPass),
501
592
  targets: [
502
593
  oitTarget(oit) ??
503
594
  (translucent === 'additive'
@@ -517,14 +608,20 @@ doubleSided = false) {
517
608
  dstFactor: 'one-minus-src-alpha',
518
609
  operation: 'add',
519
610
  },
520
- alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },
611
+ alpha: SCENE_ALPHA_COVERS,
521
612
  },
522
613
  }
523
614
  : { format: cache.format }),
524
615
  ],
525
616
  },
526
617
  primitive: { topology: 'triangle-list', cullMode: doubleSided ? 'none' : 'back' },
527
- 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
+ },
528
625
  /*
529
626
  * `less`, matching the WebGL2 path's `LESS` rather than `LEQUAL`, and for the reason
530
627
  * `drawMesh` documents there: under `LEQUAL` two coplanar surfaces do not merely tie,
@@ -532,8 +629,9 @@ doubleSided = false) {
532
629
  */
533
630
  depthStencil: {
534
631
  format: DEPTH_FORMAT,
535
- depthWriteEnabled: depthWrite,
536
- 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,
537
635
  /*
538
636
  * Baked in, where the other backend toggles it around the draw. Both read
539
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
+ }