@driftengine/core 4.8.7 → 4.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/CHANGELOG.json +123 -11
  2. package/README.md +43 -38
  3. package/dist/index.d.ts +8 -1
  4. package/dist/index.js +11 -3
  5. package/dist/render/ambientHarmonics.d.ts +1 -1
  6. package/dist/render/ambientHarmonics.js +1 -1
  7. package/dist/render/areaLights.d.ts +4 -4
  8. package/dist/render/areaLights.js +1 -1
  9. package/dist/render/atmosphere.d.ts +13 -0
  10. package/dist/render/atmosphere.js +9 -1
  11. package/dist/render/backend/api.d.ts +19 -4
  12. package/dist/render/backend/createRenderer.d.ts +6 -0
  13. package/dist/render/backend/createRenderer.js +4 -1
  14. package/dist/render/backend/select.js +11 -5
  15. package/dist/render/backend/webgl2/boneAnimations.d.ts +29 -0
  16. package/dist/render/backend/webgl2/boneAnimations.js +80 -0
  17. package/dist/render/backend/webgl2/instanced.d.ts +5 -1
  18. package/dist/render/backend/webgl2/instanced.js +13 -1
  19. package/dist/render/backend/webgl2/renderer.d.ts +180 -4
  20. package/dist/render/backend/webgl2/renderer.js +550 -40
  21. package/dist/render/backend/webgl2/skinPaletteTexture.d.ts +5 -3
  22. package/dist/render/backend/webgl2/skinPaletteTexture.js +6 -4
  23. package/dist/render/backend/webgpu/boneAnimations.d.ts +34 -0
  24. package/dist/render/backend/webgpu/boneAnimations.js +76 -0
  25. package/dist/render/backend/webgpu/buffers.d.ts +19 -4
  26. package/dist/render/backend/webgpu/buffers.js +18 -11
  27. package/dist/render/backend/webgpu/compressedUpload.d.ts +0 -1
  28. package/dist/render/backend/webgpu/compressedUpload.js +53 -8
  29. package/dist/render/backend/webgpu/depthPass.d.ts +59 -3
  30. package/dist/render/backend/webgpu/depthPass.js +49 -14
  31. package/dist/render/backend/webgpu/device.d.ts +7 -1
  32. package/dist/render/backend/webgpu/device.js +31 -3
  33. package/dist/render/backend/webgpu/drawCommand.d.ts +18 -4
  34. package/dist/render/backend/webgpu/drawCommand.js +10 -3
  35. package/dist/render/backend/webgpu/flatPass.d.ts +100 -42
  36. package/dist/render/backend/webgpu/flatPass.js +191 -43
  37. package/dist/render/backend/webgpu/instanced.d.ts +14 -1
  38. package/dist/render/backend/webgpu/instanced.js +24 -1
  39. package/dist/render/backend/webgpu/materialStore.d.ts +101 -0
  40. package/dist/render/backend/webgpu/materialStore.js +265 -0
  41. package/dist/render/backend/webgpu/pipelineCache.d.ts +6 -0
  42. package/dist/render/backend/webgpu/pipelineCache.js +7 -0
  43. package/dist/render/backend/webgpu/postPass.d.ts +51 -9
  44. package/dist/render/backend/webgpu/postPass.js +16 -2
  45. package/dist/render/backend/webgpu/reflectionSurfacePass.d.ts +30 -0
  46. package/dist/render/backend/webgpu/reflectionSurfacePass.js +100 -0
  47. package/dist/render/backend/webgpu/renderer.d.ts +283 -37
  48. package/dist/render/backend/webgpu/renderer.js +1363 -202
  49. package/dist/render/backend/webgpu/skinPaletteRing.d.ts +7 -3
  50. package/dist/render/backend/webgpu/skinPaletteRing.js +13 -7
  51. package/dist/render/backend/webgpu/skinPaletteTexture.d.ts +6 -0
  52. package/dist/render/backend/webgpu/skinPaletteTexture.js +7 -1
  53. package/dist/render/backend/webgpu/staticBundles.d.ts +125 -0
  54. package/dist/render/backend/webgpu/staticBundles.js +241 -0
  55. package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +10 -3
  56. package/dist/render/backend/webgpu/surfaceTexturePass.js +20 -2
  57. package/dist/render/backend/webgpu/uniformRing.d.ts +21 -0
  58. package/dist/render/backend/webgpu/uniformRing.js +9 -1
  59. package/dist/render/bloomChain.d.ts +3 -3
  60. package/dist/render/boneAnimation.d.ts +92 -0
  61. package/dist/render/boneAnimation.js +133 -0
  62. package/dist/render/compressedSource.d.ts +33 -13
  63. package/dist/render/compressedSource.js +70 -25
  64. package/dist/render/displayRange.d.ts +31 -0
  65. package/dist/render/displayRange.js +47 -0
  66. package/dist/render/filmicCurve.d.ts +74 -0
  67. package/dist/render/filmicCurve.js +203 -0
  68. package/dist/render/fog.d.ts +4 -1
  69. package/dist/render/fog.js +12 -2
  70. package/dist/render/frame/resources.d.ts +2 -2
  71. package/dist/render/frame/resources.js +6 -0
  72. package/dist/render/frameReflections.d.ts +40 -0
  73. package/dist/render/frameReflections.js +48 -0
  74. package/dist/render/glCompressed.js +83 -0
  75. package/dist/render/instances.d.ts +26 -0
  76. package/dist/render/lightBudget.d.ts +10 -0
  77. package/dist/render/lightBudget.js +10 -0
  78. package/dist/render/lightmap.d.ts +1 -1
  79. package/dist/render/mesh.d.ts +5 -0
  80. package/dist/render/mesh.js +6 -0
  81. package/dist/render/pass.d.ts +49 -0
  82. package/dist/render/pointLightSelection.d.ts +4 -4
  83. package/dist/render/reflectionSurfaceTargets.d.ts +28 -0
  84. package/dist/render/reflectionSurfaceTargets.js +99 -0
  85. package/dist/render/renderQuality.d.ts +39 -8
  86. package/dist/render/renderQuality.js +4 -0
  87. package/dist/render/sceneTarget.d.ts +5 -0
  88. package/dist/render/sceneTarget.js +24 -1
  89. package/dist/render/screenSpaceReflection.d.ts +7 -1
  90. package/dist/render/screenSpaceReflection.js +5 -0
  91. package/dist/render/shaders/arcane.d.ts +1 -1
  92. package/dist/render/shaders/bolt.d.ts +1 -1
  93. package/dist/render/shaders/boneAnimation.d.ts +19 -0
  94. package/dist/render/shaders/boneAnimation.js +63 -0
  95. package/dist/render/shaders/caustics.d.ts +1 -1
  96. package/dist/render/shaders/depth.d.ts +7 -0
  97. package/dist/render/shaders/depth.js +35 -10
  98. package/dist/render/shaders/film.d.ts +1 -1
  99. package/dist/render/shaders/filmLook.js +2 -1
  100. package/dist/render/shaders/fire.d.ts +1 -1
  101. package/dist/render/shaders/flat/glassTint.d.ts +1 -1
  102. package/dist/render/shaders/flat/glassTint.js +2 -0
  103. package/dist/render/shaders/flat/index.d.ts +16 -0
  104. package/dist/render/shaders/flat/index.js +33 -5
  105. package/dist/render/shaders/flat/main.d.ts +1 -1
  106. package/dist/render/shaders/flat/main.js +43 -5
  107. package/dist/render/shaders/flat/models.js +1 -1
  108. package/dist/render/shaders/flat/overlay.d.ts +16 -0
  109. package/dist/render/shaders/flat/overlay.js +117 -0
  110. package/dist/render/shaders/flat/pointShadow.js +3 -3
  111. package/dist/render/shaders/flat/preamble.js +38 -24
  112. package/dist/render/shaders/flat/reflectionSurface.d.ts +21 -0
  113. package/dist/render/shaders/flat/reflectionSurface.js +61 -0
  114. package/dist/render/shaders/fog.d.ts +1 -1
  115. package/dist/render/shaders/fog.js +9 -2
  116. package/dist/render/shaders/fringe.d.ts +29 -0
  117. package/dist/render/shaders/fringe.js +55 -0
  118. package/dist/render/shaders/generated/arcane.wgsl.d.ts +1 -1
  119. package/dist/render/shaders/generated/arcane.wgsl.js +1 -1
  120. package/dist/render/shaders/generated/bolt.wgsl.d.ts +1 -1
  121. package/dist/render/shaders/generated/bolt.wgsl.js +1 -1
  122. package/dist/render/shaders/generated/caustics.wgsl.d.ts +1 -1
  123. package/dist/render/shaders/generated/caustics.wgsl.js +1 -1
  124. package/dist/render/shaders/generated/depth.wgsl.d.ts +93 -0
  125. package/dist/render/shaders/generated/depth.wgsl.js +93 -0
  126. package/dist/render/shaders/generated/film.wgsl.d.ts +1 -1
  127. package/dist/render/shaders/generated/film.wgsl.js +1 -1
  128. package/dist/render/shaders/generated/fire.wgsl.d.ts +1 -1
  129. package/dist/render/shaders/generated/fire.wgsl.js +1 -1
  130. package/dist/render/shaders/generated/flat.wgsl.d.ts +3254 -2920
  131. package/dist/render/shaders/generated/flat.wgsl.js +3292 -2957
  132. package/dist/render/shaders/generated/line.wgsl.d.ts +1 -1
  133. package/dist/render/shaders/generated/line.wgsl.js +1 -1
  134. package/dist/render/shaders/generated/particle.wgsl.d.ts +4 -4
  135. package/dist/render/shaders/generated/particle.wgsl.js +4 -4
  136. package/dist/render/shaders/generated/rush.wgsl.d.ts +56 -26
  137. package/dist/render/shaders/generated/rush.wgsl.js +56 -26
  138. package/dist/render/shaders/generated/scatter.wgsl.d.ts +1 -1
  139. package/dist/render/shaders/generated/scatter.wgsl.js +1 -1
  140. package/dist/render/shaders/generated/smoke.wgsl.d.ts +1 -1
  141. package/dist/render/shaders/generated/smoke.wgsl.js +1 -1
  142. package/dist/render/shaders/generated/ssrResolve.wgsl.d.ts +29 -0
  143. package/dist/render/shaders/generated/ssrResolve.wgsl.js +29 -0
  144. package/dist/render/shaders/generated/ssrTrace.wgsl.d.ts +22 -2
  145. package/dist/render/shaders/generated/ssrTrace.wgsl.js +22 -2
  146. package/dist/render/shaders/generated/water.wgsl.d.ts +1 -1
  147. package/dist/render/shaders/generated/water.wgsl.js +1 -1
  148. package/dist/render/shaders/gpudriven/fog.wgsl.d.ts +2 -2
  149. package/dist/render/shaders/gpudriven/fog.wgsl.js +11 -3
  150. package/dist/render/shaders/line.d.ts +1 -1
  151. package/dist/render/shaders/outputTransform.d.ts +7 -0
  152. package/dist/render/shaders/outputTransform.js +28 -14
  153. package/dist/render/shaders/particle.d.ts +3 -3
  154. package/dist/render/shaders/rush.js +54 -11
  155. package/dist/render/shaders/scatter.d.ts +1 -1
  156. package/dist/render/shaders/smoke.d.ts +1 -1
  157. package/dist/render/shaders/ssrResolve.d.ts +17 -0
  158. package/dist/render/shaders/ssrResolve.js +51 -0
  159. package/dist/render/shaders/ssrTrace.js +26 -0
  160. package/dist/render/shaders/vertexChannel.d.ts +7 -0
  161. package/dist/render/shaders/vertexChannel.js +26 -0
  162. package/dist/render/shaders/water.d.ts +1 -1
  163. package/dist/render/ssrPass.d.ts +16 -0
  164. package/dist/render/ssrPass.js +106 -1
  165. package/dist/render/staticDraws.d.ts +47 -0
  166. package/dist/render/staticDraws.js +43 -0
  167. package/dist/render/surfaceOverlay.d.ts +132 -0
  168. package/dist/render/surfaceOverlay.js +85 -0
  169. package/dist/render/surfaceTexture.d.ts +57 -7
  170. package/dist/render/surfaceTexture.js +125 -17
  171. package/dist/render/temporalAa.d.ts +14 -0
  172. package/dist/render/temporalAa.js +20 -0
  173. package/dist/render/vertexDefaults.d.ts +17 -0
  174. package/dist/render/vertexDefaults.js +24 -0
  175. package/package.json +6 -6
  176. package/src/index.ts +24 -2
  177. package/src/render/ambientHarmonics.ts +1 -1
  178. package/src/render/areaLights.ts +4 -4
  179. package/src/render/atmosphere.ts +22 -1
  180. package/src/render/backend/api.ts +22 -3
  181. package/src/render/backend/createRenderer.ts +18 -1
  182. package/src/render/backend/select.ts +10 -5
  183. package/src/render/backend/webgl2/boneAnimations.ts +105 -0
  184. package/src/render/backend/webgl2/instanced.ts +20 -1
  185. package/src/render/backend/webgl2/renderer.ts +672 -37
  186. package/src/render/backend/webgl2/skinPaletteTexture.ts +6 -4
  187. package/src/render/backend/webgpu/boneAnimations.ts +97 -0
  188. package/src/render/backend/webgpu/buffers.ts +42 -16
  189. package/src/render/backend/webgpu/compressedUpload.ts +59 -9
  190. package/src/render/backend/webgpu/depthPass.ts +51 -10
  191. package/src/render/backend/webgpu/device.ts +42 -3
  192. package/src/render/backend/webgpu/drawCommand.ts +22 -4
  193. package/src/render/backend/webgpu/flatPass.ts +250 -40
  194. package/src/render/backend/webgpu/instanced.ts +32 -1
  195. package/src/render/backend/webgpu/materialStore.ts +276 -0
  196. package/src/render/backend/webgpu/pipelineCache.ts +7 -0
  197. package/src/render/backend/webgpu/postPass.ts +18 -0
  198. package/src/render/backend/webgpu/reflectionSurfacePass.ts +114 -0
  199. package/src/render/backend/webgpu/renderer.ts +1655 -230
  200. package/src/render/backend/webgpu/skinPaletteRing.ts +13 -7
  201. package/src/render/backend/webgpu/skinPaletteTexture.ts +7 -1
  202. package/src/render/backend/webgpu/staticBundles.ts +363 -0
  203. package/src/render/backend/webgpu/surfaceTexturePass.ts +29 -3
  204. package/src/render/backend/webgpu/uniformRing.ts +10 -1
  205. package/src/render/bloomChain.ts +3 -3
  206. package/src/render/boneAnimation.ts +223 -0
  207. package/src/render/compressedSource.ts +121 -29
  208. package/src/render/displayRange.ts +61 -0
  209. package/src/render/filmicCurve.ts +229 -0
  210. package/src/render/fog.ts +19 -3
  211. package/src/render/frame/resources.ts +6 -0
  212. package/src/render/frameReflections.ts +72 -0
  213. package/src/render/glCompressed.ts +83 -0
  214. package/src/render/instances.ts +27 -0
  215. package/src/render/lightBudget.ts +11 -0
  216. package/src/render/lightmap.ts +1 -1
  217. package/src/render/mesh.ts +6 -0
  218. package/src/render/pass.ts +53 -1
  219. package/src/render/pointLightSelection.ts +4 -4
  220. package/src/render/reflectionSurfaceTargets.ts +105 -0
  221. package/src/render/renderQuality.ts +44 -8
  222. package/src/render/sceneTarget.ts +30 -2
  223. package/src/render/screenSpaceReflection.ts +7 -1
  224. package/src/render/shaders/boneAnimation.ts +63 -0
  225. package/src/render/shaders/depth.ts +45 -10
  226. package/src/render/shaders/filmLook.ts +2 -1
  227. package/src/render/shaders/flat/glassTint.ts +5 -1
  228. package/src/render/shaders/flat/index.ts +49 -5
  229. package/src/render/shaders/flat/main.ts +43 -5
  230. package/src/render/shaders/flat/models.ts +1 -1
  231. package/src/render/shaders/flat/overlay.ts +117 -0
  232. package/src/render/shaders/flat/pointShadow.ts +3 -3
  233. package/src/render/shaders/flat/preamble.ts +38 -24
  234. package/src/render/shaders/flat/reflectionSurface.ts +61 -0
  235. package/src/render/shaders/fog.ts +9 -2
  236. package/src/render/shaders/fringe.ts +59 -0
  237. package/src/render/shaders/generated/arcane.wgsl.ts +1 -1
  238. package/src/render/shaders/generated/bolt.wgsl.ts +1 -1
  239. package/src/render/shaders/generated/caustics.wgsl.ts +1 -1
  240. package/src/render/shaders/generated/depth.wgsl.ts +95 -0
  241. package/src/render/shaders/generated/film.wgsl.ts +1 -1
  242. package/src/render/shaders/generated/fire.wgsl.ts +1 -1
  243. package/src/render/shaders/generated/flat.wgsl.ts +3292 -2957
  244. package/src/render/shaders/generated/line.wgsl.ts +1 -1
  245. package/src/render/shaders/generated/particle.wgsl.ts +4 -4
  246. package/src/render/shaders/generated/rush.wgsl.ts +56 -26
  247. package/src/render/shaders/generated/scatter.wgsl.ts +1 -1
  248. package/src/render/shaders/generated/smoke.wgsl.ts +1 -1
  249. package/src/render/shaders/generated/ssrResolve.wgsl.ts +30 -0
  250. package/src/render/shaders/generated/ssrTrace.wgsl.ts +22 -2
  251. package/src/render/shaders/generated/water.wgsl.ts +1 -1
  252. package/src/render/shaders/gpudriven/fog.wgsl.ts +11 -3
  253. package/src/render/shaders/outputTransform.ts +30 -14
  254. package/src/render/shaders/rush.ts +54 -11
  255. package/src/render/shaders/ssrResolve.ts +52 -0
  256. package/src/render/shaders/ssrTrace.ts +26 -0
  257. package/src/render/shaders/vertexChannel.ts +27 -0
  258. package/src/render/ssrPass.ts +138 -1
  259. package/src/render/staticDraws.ts +95 -0
  260. package/src/render/surfaceOverlay.ts +195 -0
  261. package/src/render/surfaceTexture.ts +161 -27
  262. package/src/render/temporalAa.ts +20 -0
  263. package/src/render/vertexDefaults.ts +28 -0
@@ -7,7 +7,8 @@ import type { ProbeBakeOptions } from '../reflectionProbe.ts';
7
7
  import type { Renderer, TranslucentMeshOptions } from './webgl2/renderer.ts';
8
8
  import type { InstancedOptions, MeshInstances } from '../instances.ts';
9
9
  import type { SurfaceMaterial } from '../surfaceTexture.ts';
10
- import type { SurfaceSource } from '../compressedSource.ts';
10
+ import type { SurfaceOverlay } from '../surfaceOverlay.ts';
11
+ import type { CompressedTextureSource, SurfaceSource } from '../compressedSource.ts';
11
12
  import type { LightmapPage } from '../lightmap.ts';
12
13
  import type { DeviceParticles } from '../particlePool.ts';
13
14
  import type { ClothBindingData } from '../clothBindingData.ts';
@@ -311,6 +312,7 @@ export type RendererApi = Omit<
311
312
  | 'disposeSurfaceTexture'
312
313
  | 'setSurfaceTexture'
313
314
  | 'setMaterial'
315
+ | 'setSurfaceOverlay'
314
316
  | 'createClothBinding'
315
317
  | 'createClothParticles'
316
318
  | 'updateClothParticles'
@@ -341,6 +343,13 @@ export type RendererApi = Omit<
341
343
  setCloth(binding: ClothBindingHandle | null, particles?: ClothParticlesHandle | null): void;
342
344
  disposeClothBinding(binding: ClothBindingHandle): void;
343
345
  disposeClothParticles(particles: ClothParticlesHandle): void;
346
+ /**
347
+ * What the following draws lay over their surfaces beyond their materials — a rim of light, a
348
+ * dissolve with a glowing edge, wrinkle normals by region — or null for none, which every pass
349
+ * starts with. Per draw, so one character's whole set of materials changes together. Its images
350
+ * are regions of one atlas (`SurfaceOverlay.maps`). See `surfaceOverlay.ts`.
351
+ */
352
+ setSurfaceOverlay(overlay: SurfaceOverlay | null): void;
344
353
  /**
345
354
  * Upload a caller's image, or a BC image's blocks with their stored chain where
346
355
  * `compressedFormats` has the format. See `SurfaceTextureHandle` for the boundary this guards.
@@ -406,12 +415,22 @@ export type RendererApi = Omit<
406
415
  ): boolean;
407
416
 
408
417
  /**
409
- * Replace a texture's pixels, keeping the GPU object and its sampler state.
418
+ * Replace a texture's pixels, keeping the handle and its sampler state.
410
419
  *
411
420
  * The binding a draw loop already holds stays valid, so the swap is a swap rather than a
412
421
  * rebuild. Not a hot path: it re-uploads the whole image and rebuilds the mip chain.
422
+ *
423
+ * **Blocks may replace an image**, at the format's own size and with the chain they carry: the
424
+ * same picture at a fraction of the memory, which is how a loader that first showed a decoded
425
+ * image hands the device the blocks it encoded afterwards. Read in the colour space the texture
426
+ * was made with, and refused as `createSurfaceTexture` refuses them where the device does not take
427
+ * that format (`compressedFormats`). **The way back is refused**: a texture holding blocks takes
428
+ * no image, since nothing could say what its chain should become.
413
429
  */
414
- updateSurfaceTexture(texture: SurfaceTextureHandle, source: TexImageSource): void;
430
+ updateSurfaceTexture(
431
+ texture: SurfaceTextureHandle,
432
+ source: TexImageSource | CompressedTextureSource,
433
+ ): void;
415
434
 
416
435
  disposeSurfaceTexture(texture: SurfaceTextureHandle): void;
417
436
 
@@ -5,6 +5,7 @@ import { BACKEND_TIMEOUT_MS, forcedBackend, selectBackend } from './select.ts';
5
5
  import { TIMED_OUT, withDeadline } from './deadline.ts';
6
6
  import { mountSplash, type MountedSplash, type SplashOptions } from '../../ui/splash.ts';
7
7
  import { gpuDrivenRefusal, gpuDrivenSupported } from '../gpudriven/pipeline.ts';
8
+ import { browserHighDynamicRange, chooseDisplayRange } from '../displayRange.ts';
8
9
 
9
10
  /**
10
11
  * Which of the two pipelines is drawing.
@@ -149,6 +150,12 @@ export interface CreateRendererOptions {
149
150
  * badge is looked at on a deployed build.
150
151
  */
151
152
  readonly splash?: boolean | SplashOptions;
153
+ /**
154
+ * Whether the display shows a high dynamic range, asked only where `highDynamicRange` was. The
155
+ * browser's `(dynamic-range: high)` query by default; a host with no DOM, or one that knows
156
+ * better about its own display, answers instead. See `displayRange.ts`.
157
+ */
158
+ readonly highDynamicRangeDisplay?: () => boolean;
152
159
  }
153
160
 
154
161
  /** What was built, and which path built it. */
@@ -370,7 +377,17 @@ export async function createRenderer(
370
377
  const { createGpuSurface } = await import('./webgpu/device.ts');
371
378
  const { WebGPURenderer } = await import('./webgpu/renderer.ts');
372
379
  stage = 'creating the surface';
373
- const surface = createGpuSurface(canvas, device);
380
+ const profile = resolveRenderQuality(qualityFor('webgpu'));
381
+ const surface = createGpuSurface(
382
+ canvas,
383
+ device,
384
+ chooseDisplayRange(
385
+ profile.highDynamicRange,
386
+ profile.screenEffects && profile.hdrScene,
387
+ profile.highDynamicRange &&
388
+ (options.highDynamicRangeDisplay ?? browserHighDynamicRange)(),
389
+ ),
390
+ );
374
391
  stage = 'constructing the renderer';
375
392
  return { surface, WebGPURenderer };
376
393
  })();
@@ -248,12 +248,17 @@ async function acquireWebGpu(
248
248
  features.push('timestamp-query');
249
249
  }
250
250
  /*
251
- * BC compressed textures, on the same terms: asked for wherever the adapter offers it, because
252
- * a device without it still draws — the loader decodes for it — and one with it samples a BC7
253
- * texture at a byte a texel instead of four. See `compressedUpload.ts`.
251
+ * The three block families, on the same terms: each asked for wherever the adapter offers it,
252
+ * because a device without one still draws — the loader decodes, or encodes ETC2, for it — and
253
+ * one with it samples a texture at a byte a texel or half of one instead of four. Desktops
254
+ * offer BC; phones ETC2 and ASTC. See `compressedUpload.ts`.
254
255
  */
255
- if (adapter.features?.has('texture-compression-bc') === true) {
256
- features.push('texture-compression-bc');
256
+ for (const family of [
257
+ 'texture-compression-bc',
258
+ 'texture-compression-etc2',
259
+ 'texture-compression-astc',
260
+ ] as const) {
261
+ if (adapter.features?.has(family) === true) features.push(family);
257
262
  }
258
263
  const descriptor: GPUDeviceDescriptor = {};
259
264
  if (Object.keys(required).length > 0) descriptor.requiredLimits = required;
@@ -0,0 +1,105 @@
1
+ /**
2
+ * A bone animation's textures on this backend, and a batch's clocks: what
3
+ * `shaders/boneAnimation.ts` reads with `texelFetch`, made once and never filtered. The twin of
4
+ * `webgpu/boneAnimations.ts`, at the same formats for the same reason: a turn in half floats jitters
5
+ * a crowd's hands at the frame's rate.
6
+ */
7
+ import {
8
+ CLOCK_TEXTURE_WIDTH,
9
+ type BoneAnimationHandle,
10
+ type BoneAnimationTexels,
11
+ } from '../../boneAnimation.ts';
12
+
13
+ /**
14
+ * A float texture read by index: one level, nearest, clamped. Bound on unit 0, chosen rather than
15
+ * inherited, for the reason `oitPass.ts` gives: `bindTexture` binds to whatever unit is active, and
16
+ * a frame leaves that wherever its last pass finished.
17
+ */
18
+ function floatTexture(
19
+ gl: WebGL2RenderingContext,
20
+ internal: number,
21
+ width: number,
22
+ height: number,
23
+ ): WebGLTexture {
24
+ const texture = gl.createTexture();
25
+ if (texture === null) throw new Error('boneAnimations: createTexture failed');
26
+ gl.activeTexture(gl.TEXTURE0);
27
+ gl.bindTexture(gl.TEXTURE_2D, texture);
28
+ gl.texStorage2D(gl.TEXTURE_2D, 1, internal, width, height);
29
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
30
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
31
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
32
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
33
+ return texture;
34
+ }
35
+
36
+ /** A clip on the device, from `createBoneAnimation`. */
37
+ export class GlBoneAnimation implements BoneAnimationHandle {
38
+ readonly bones: number;
39
+ readonly frames: number;
40
+ readonly framesPerSecond: number;
41
+ readonly boneScale: number;
42
+ readonly places: WebGLTexture;
43
+ readonly turns: WebGLTexture;
44
+ disposed = false;
45
+
46
+ constructor(gl: WebGL2RenderingContext, texels: BoneAnimationTexels) {
47
+ this.bones = texels.bones;
48
+ this.frames = texels.frames;
49
+ this.framesPerSecond = texels.framesPerSecond;
50
+ this.boneScale = texels.boneScale;
51
+ const make = (data: Float32Array): WebGLTexture => {
52
+ const texture = floatTexture(gl, gl.RGBA32F, texels.bones, texels.frames);
53
+ gl.texSubImage2D(
54
+ gl.TEXTURE_2D,
55
+ 0,
56
+ 0,
57
+ 0,
58
+ texels.bones,
59
+ texels.frames,
60
+ gl.RGBA,
61
+ gl.FLOAT,
62
+ data,
63
+ );
64
+ return texture;
65
+ };
66
+ this.places = make(texels.places);
67
+ this.turns = make(texels.turns);
68
+ gl.bindTexture(gl.TEXTURE_2D, null);
69
+ }
70
+
71
+ dispose(gl: WebGL2RenderingContext): void {
72
+ this.disposed = true;
73
+ gl.deleteTexture(this.places);
74
+ gl.deleteTexture(this.turns);
75
+ }
76
+ }
77
+
78
+ /** A batch's clocks: two floats an instance, wrapped onto rows `CLOCK_TEXTURE_WIDTH` wide. */
79
+ export class GlInstanceClocks {
80
+ readonly texture: WebGLTexture;
81
+ readonly staging: Float32Array;
82
+ private readonly width: number;
83
+
84
+ constructor(gl: WebGL2RenderingContext, capacity: number) {
85
+ this.width = Math.max(1, Math.min(capacity, CLOCK_TEXTURE_WIDTH));
86
+ const rows = Math.max(1, Math.ceil(capacity / this.width));
87
+ this.staging = new Float32Array(this.width * rows * 2);
88
+ this.texture = floatTexture(gl, gl.RG32F, this.width, rows);
89
+ gl.bindTexture(gl.TEXTURE_2D, null);
90
+ }
91
+
92
+ /** The rows that hold the first `count` instances, from `staging`. */
93
+ upload(gl: WebGL2RenderingContext, count: number): void {
94
+ if (count <= 0) return;
95
+ const rows = Math.ceil(count / this.width);
96
+ gl.activeTexture(gl.TEXTURE0);
97
+ gl.bindTexture(gl.TEXTURE_2D, this.texture);
98
+ gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, this.width, rows, gl.RG, gl.FLOAT, this.staging);
99
+ gl.bindTexture(gl.TEXTURE_2D, null);
100
+ }
101
+
102
+ dispose(gl: WebGL2RenderingContext): void {
103
+ gl.deleteTexture(this.texture);
104
+ }
105
+ }
@@ -8,6 +8,8 @@ import {
8
8
  import type { MeshInstances } from '../../instances.ts';
9
9
  import type { Mesh } from '../../mesh.ts';
10
10
  import type { FrustumPlanes } from '../../../math/frustum.ts';
11
+ import { packInstanceClocks } from '../../boneAnimation.ts';
12
+ import { GlInstanceClocks, type GlBoneAnimation } from './boneAnimations.ts';
11
13
 
12
14
  /**
13
15
  * One batch of a mesh: its per-instance buffer and a vertex array of its own.
@@ -42,10 +44,22 @@ export class InstancedBatch {
42
44
  readonly instances: MeshInstances;
43
45
  } | null;
44
46
 
45
- constructor(gl: WebGL2RenderingContext, mesh: Mesh, capacity: number, cull = false) {
47
+ /** The bone animation every instance plays, and its clocks; null for a batch that plays none. */
48
+ readonly animation: GlBoneAnimation | null;
49
+ readonly clocks: GlInstanceClocks | null;
50
+
51
+ constructor(
52
+ gl: WebGL2RenderingContext,
53
+ mesh: Mesh,
54
+ capacity: number,
55
+ cull = false,
56
+ animation: GlBoneAnimation | null = null,
57
+ ) {
46
58
  this.mesh = mesh;
47
59
  this.capacity = capacity;
48
60
  this.cull = cull;
61
+ this.animation = animation;
62
+ this.clocks = animation === null ? null : new GlInstanceClocks(gl, capacity);
49
63
  this.staging = new Float32Array(capacity * INSTANCE_FLOATS);
50
64
  this.buffer = allocate(gl, capacity);
51
65
  this.vao = mesh.createInstanceArray(gl, this.buffer, INSTANCE_STRIDE);
@@ -68,6 +82,10 @@ export class InstancedBatch {
68
82
  packInstances(data, this.staging);
69
83
  gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
70
84
  gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.staging, 0, count * INSTANCE_FLOATS);
85
+ if (this.clocks !== null) {
86
+ packInstanceClocks(data, this.clocks.staging);
87
+ this.clocks.upload(gl, count);
88
+ }
71
89
  }
72
90
 
73
91
  /** Draw the first `count` uploaded instances: every draw but a culling camera draw. */
@@ -102,6 +120,7 @@ export class InstancedBatch {
102
120
  dispose(gl: WebGL2RenderingContext): void {
103
121
  gl.deleteVertexArray(this.vao);
104
122
  gl.deleteBuffer(this.buffer);
123
+ this.clocks?.dispose(gl);
105
124
  if (this.kept !== null) {
106
125
  gl.deleteVertexArray(this.kept.vao);
107
126
  gl.deleteBuffer(this.kept.buffer);