@woosh/meep-engine 3.68.0 → 3.69.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 (190) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/editor/ecs/component/editors/ecs/Trail3DEditor.d.ts +2 -17
  3. package/editor/ecs/component/editors/ecs/Trail3DEditor.d.ts.map +1 -1
  4. package/editor/ecs/component/editors/ecs/Trail3DEditor.js +3 -18
  5. package/package.json +1 -1
  6. package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts +33 -65
  7. package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts.map +1 -1
  8. package/src/engine/graphics/ecs/trail3d/Trail3D.js +37 -245
  9. package/src/engine/graphics/ecs/trail3d/Trail3DFlags.d.ts +0 -4
  10. package/src/engine/graphics/ecs/trail3d/Trail3DFlags.js +4 -10
  11. package/src/engine/graphics/ecs/trail3d/seed_trail_stroke.d.ts +13 -10
  12. package/src/engine/graphics/ecs/trail3d/seed_trail_stroke.d.ts.map +1 -1
  13. package/src/engine/graphics/ecs/trail3d/seed_trail_stroke.js +28 -37
  14. package/src/engine/graphics/ecs/trail3d/trail_knot_count.d.ts +10 -0
  15. package/src/engine/graphics/ecs/trail3d/trail_knot_count.d.ts.map +1 -0
  16. package/src/engine/graphics/ecs/trail3d/trail_knot_count.js +27 -0
  17. package/src/engine/graphics/trail/TrailKnots.d.ts +62 -0
  18. package/src/engine/graphics/trail/TrailKnots.d.ts.map +1 -0
  19. package/src/engine/graphics/trail/TrailKnots.js +137 -0
  20. package/src/engine/graphics/trail/tube/TubeXMaterialSpec.d.ts +1 -1
  21. package/src/engine/graphics/trail/tube/TubeXMaterialSpec.js +1 -1
  22. package/src/engine/graphics3/EntityRowHold.d.ts +48 -0
  23. package/src/engine/graphics3/EntityRowHold.d.ts.map +1 -0
  24. package/src/engine/graphics3/EntityRowHold.js +128 -0
  25. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +6 -2
  26. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
  27. package/src/engine/graphics3/GPUParticleEmitterSystem.js +11 -44
  28. package/src/engine/graphics3/Trail3DSystem.d.ts +69 -35
  29. package/src/engine/graphics3/Trail3DSystem.d.ts.map +1 -1
  30. package/src/engine/graphics3/Trail3DSystem.js +380 -81
  31. package/src/engine/physics/fluid/ecs/FluidObstacle.d.ts +17 -0
  32. package/src/engine/physics/fluid/ecs/FluidObstacle.d.ts.map +1 -1
  33. package/src/engine/physics/fluid/ecs/FluidObstacle.js +22 -2
  34. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +6 -5
  35. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts.map +1 -1
  36. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.js +14 -3
  37. package/src/engine/physics/fluid/obstacle/FLUID_OBSTACLE_RECORD_STRUCT.d.ts +9 -1
  38. package/src/engine/physics/fluid/obstacle/FLUID_OBSTACLE_RECORD_STRUCT.d.ts.map +1 -1
  39. package/src/engine/physics/fluid/obstacle/FLUID_OBSTACLE_RECORD_STRUCT.js +11 -1
  40. package/src/engine/physics/fluid/obstacle/fluid_obstacle_record_create.d.ts +5 -0
  41. package/src/engine/physics/fluid/obstacle/fluid_obstacle_record_create.d.ts.map +1 -1
  42. package/src/engine/physics/fluid/obstacle/fluid_obstacle_record_create.js +2 -0
  43. package/src/engine/physics/fluid/obstacle/fluid_obstacle_write_gpu_record.d.ts +4 -3
  44. package/src/engine/physics/fluid/obstacle/fluid_obstacle_write_gpu_record.d.ts.map +1 -1
  45. package/src/engine/physics/fluid/obstacle/fluid_obstacle_write_gpu_record.js +11 -3
  46. package/src/shade/playground/trails/index.html +50 -0
  47. package/src/shade/playground/trails/main.d.ts +2 -0
  48. package/src/shade/playground/trails/main.d.ts.map +1 -0
  49. package/src/shade/playground/trails/main.js +258 -0
  50. package/src/shade/renderer/animation/animation_curve_write_keys.d.ts +18 -0
  51. package/src/shade/renderer/animation/animation_curve_write_keys.d.ts.map +1 -0
  52. package/src/shade/renderer/animation/animation_curve_write_keys.js +34 -0
  53. package/src/shade/renderer/deferred/tonemap/ColorGrade.d.ts.map +1 -1
  54. package/src/shade/renderer/deferred/tonemap/ColorGrade.js +13 -36
  55. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +2 -2
  56. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_avboit_vertex.d.ts +2 -13
  57. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_avboit_vertex.d.ts.map +1 -1
  58. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_avboit_vertex.js +6 -21
  59. package/src/shade/renderer/dynamic/graph_dynamic_mesh_avboit.d.ts +17 -6
  60. package/src/shade/renderer/dynamic/graph_dynamic_mesh_avboit.d.ts.map +1 -1
  61. package/src/shade/renderer/dynamic/graph_dynamic_mesh_avboit.js +38 -178
  62. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_draw.d.ts +7 -9
  63. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_draw.d.ts.map +1 -1
  64. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_draw.js +17 -106
  65. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.d.ts +7 -17
  66. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.d.ts.map +1 -1
  67. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.js +18 -118
  68. package/src/shade/renderer/fluid/forcing/FLUID_FORCING.d.ts +14 -0
  69. package/src/shade/renderer/fluid/forcing/FLUID_FORCING.d.ts.map +1 -1
  70. package/src/shade/renderer/fluid/forcing/FLUID_FORCING.js +18 -0
  71. package/src/shade/renderer/fluid/forcing/FLUID_FORCING_APPLY_STRUCT.d.ts +3 -1
  72. package/src/shade/renderer/fluid/forcing/FLUID_FORCING_APPLY_STRUCT.d.ts.map +1 -1
  73. package/src/shade/renderer/fluid/forcing/FLUID_FORCING_APPLY_STRUCT.js +4 -1
  74. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +9 -0
  75. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts.map +1 -1
  76. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.js +20 -4
  77. package/src/shade/renderer/fluid/forcing/chunk_fluid_forcing_cell.d.ts +11 -2
  78. package/src/shade/renderer/fluid/forcing/chunk_fluid_forcing_cell.d.ts.map +1 -1
  79. package/src/shade/renderer/fluid/forcing/chunk_fluid_forcing_cell.js +59 -2
  80. package/src/shade/renderer/fluid/forcing/shader_fluid_forcing_apply.d.ts +4 -1
  81. package/src/shade/renderer/fluid/forcing/shader_fluid_forcing_apply.d.ts.map +1 -1
  82. package/src/shade/renderer/fluid/forcing/shader_fluid_forcing_apply.js +367 -341
  83. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_correct.d.ts +6 -2
  84. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_correct.d.ts.map +1 -1
  85. package/src/shade/renderer/fluid/mac/shader_fluid_mac_advect_correct.js +339 -282
  86. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts +3 -2
  87. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts.map +1 -1
  88. package/src/shade/renderer/grass/press/shader_grass_press_mark.js +5 -3
  89. package/src/shade/renderer/rasterize/native/avboit/avboit_unlit_draw.d.ts +49 -0
  90. package/src/shade/renderer/rasterize/native/avboit/avboit_unlit_draw.d.ts.map +1 -0
  91. package/src/shade/renderer/rasterize/native/avboit/avboit_unlit_draw.js +144 -0
  92. package/src/shade/renderer/rasterize/native/avboit/avboit_unlit_splat.d.ts +71 -0
  93. package/src/shade/renderer/rasterize/native/avboit/avboit_unlit_splat.d.ts.map +1 -0
  94. package/src/shade/renderer/rasterize/native/avboit/avboit_unlit_splat.js +152 -0
  95. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_unlit_varyings.d.ts +21 -0
  96. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_unlit_varyings.d.ts.map +1 -0
  97. package/src/shade/renderer/rasterize/native/avboit/chunk_avboit_unlit_varyings.js +30 -0
  98. package/src/shade/renderer/rasterize/native/avboit/graph_avboit_unlit.d.ts +101 -0
  99. package/src/shade/renderer/rasterize/native/avboit/graph_avboit_unlit.d.ts.map +1 -0
  100. package/src/shade/renderer/rasterize/native/avboit/graph_avboit_unlit.js +306 -0
  101. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.d.ts +9 -0
  102. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.d.ts.map +1 -1
  103. package/src/shade/renderer/rasterize/native/avboit/shader_avboit_splat.js +11 -4
  104. package/src/shade/renderer/trails/GPUTrailAVBOITChannel.d.ts +69 -0
  105. package/src/shade/renderer/trails/GPUTrailAVBOITChannel.d.ts.map +1 -0
  106. package/src/shade/renderer/trails/GPUTrailAVBOITChannel.js +129 -0
  107. package/src/shade/renderer/trails/GPUTrailSystem.d.ts +164 -0
  108. package/src/shade/renderer/trails/GPUTrailSystem.d.ts.map +1 -0
  109. package/src/shade/renderer/trails/GPUTrailSystem.js +725 -0
  110. package/src/shade/renderer/trails/data/TRAIL_DATABASE_SPEC.d.ts +14 -0
  111. package/src/shade/renderer/trails/data/TRAIL_DATABASE_SPEC.d.ts.map +1 -0
  112. package/src/shade/renderer/trails/data/TRAIL_DATABASE_SPEC.js +38 -0
  113. package/src/shade/renderer/trails/data/TRAIL_KNOT.d.ts +66 -0
  114. package/src/shade/renderer/trails/data/TRAIL_KNOT.d.ts.map +1 -0
  115. package/src/shade/renderer/trails/data/TRAIL_KNOT.js +154 -0
  116. package/src/shade/renderer/trails/data/TRAIL_RECORD.d.ts +19 -0
  117. package/src/shade/renderer/trails/data/TRAIL_RECORD.d.ts.map +1 -0
  118. package/src/shade/renderer/trails/data/TRAIL_RECORD.js +68 -0
  119. package/src/shade/renderer/trails/data/TRAIL_STATE.d.ts +18 -0
  120. package/src/shade/renderer/trails/data/TRAIL_STATE.d.ts.map +1 -0
  121. package/src/shade/renderer/trails/data/TRAIL_STATE.js +43 -0
  122. package/src/shade/renderer/trails/graph_trails.d.ts +58 -0
  123. package/src/shade/renderer/trails/graph_trails.d.ts.map +1 -0
  124. package/src/shade/renderer/trails/graph_trails.js +155 -0
  125. package/src/shade/renderer/trails/graph_trails_avboit.d.ts +126 -0
  126. package/src/shade/renderer/trails/graph_trails_avboit.d.ts.map +1 -0
  127. package/src/shade/renderer/trails/graph_trails_avboit.js +300 -0
  128. package/src/shade/renderer/trails/runtime/TrailFadeCurves.d.ts +56 -0
  129. package/src/shade/renderer/trails/runtime/TrailFadeCurves.d.ts.map +1 -0
  130. package/src/shade/renderer/trails/runtime/TrailFadeCurves.js +220 -0
  131. package/src/shade/renderer/trails/runtime/TrailKnotPool.d.ts +49 -0
  132. package/src/shade/renderer/trails/runtime/TrailKnotPool.d.ts.map +1 -0
  133. package/src/shade/renderer/trails/runtime/TrailKnotPool.js +162 -0
  134. package/src/shade/renderer/trails/runtime/TrailParameters.d.ts +52 -0
  135. package/src/shade/renderer/trails/runtime/TrailParameters.d.ts.map +1 -0
  136. package/src/shade/renderer/trails/runtime/TrailParameters.js +126 -0
  137. package/src/shade/renderer/trails/shaders/chunk_trail_frame_transport.d.ts +23 -0
  138. package/src/shade/renderer/trails/shaders/chunk_trail_frame_transport.d.ts.map +1 -0
  139. package/src/shade/renderer/trails/shaders/chunk_trail_frame_transport.js +57 -0
  140. package/src/shade/renderer/trails/shaders/chunk_trail_knot_alpha.d.ts +14 -0
  141. package/src/shade/renderer/trails/shaders/chunk_trail_knot_alpha.d.ts.map +1 -0
  142. package/src/shade/renderer/trails/shaders/chunk_trail_knot_alpha.js +40 -0
  143. package/src/shade/renderer/trails/shaders/chunk_trail_seed.d.ts +18 -0
  144. package/src/shade/renderer/trails/shaders/chunk_trail_seed.d.ts.map +1 -0
  145. package/src/shade/renderer/trails/shaders/chunk_trail_seed.js +64 -0
  146. package/src/shade/renderer/trails/shaders/chunk_trail_segment.d.ts +14 -0
  147. package/src/shade/renderer/trails/shaders/chunk_trail_segment.d.ts.map +1 -0
  148. package/src/shade/renderer/trails/shaders/chunk_trail_segment.js +51 -0
  149. package/src/shade/renderer/trails/shaders/chunk_trail_update.d.ts +48 -0
  150. package/src/shade/renderer/trails/shaders/chunk_trail_update.d.ts.map +1 -0
  151. package/src/shade/renderer/trails/shaders/chunk_trail_update.js +197 -0
  152. package/src/shade/renderer/trails/shaders/chunk_trail_vertex.d.ts +34 -0
  153. package/src/shade/renderer/trails/shaders/chunk_trail_vertex.d.ts.map +1 -0
  154. package/src/shade/renderer/trails/shaders/chunk_trail_vertex.js +111 -0
  155. package/src/shade/renderer/trails/shaders/shader_trail_avboit.d.ts +24 -0
  156. package/src/shade/renderer/trails/shaders/shader_trail_avboit.d.ts.map +1 -0
  157. package/src/shade/renderer/trails/shaders/shader_trail_avboit.js +78 -0
  158. package/src/shade/renderer/trails/shaders/shader_trail_avboit_segments.d.ts +23 -0
  159. package/src/shade/renderer/trails/shaders/shader_trail_avboit_segments.d.ts.map +1 -0
  160. package/src/shade/renderer/trails/shaders/shader_trail_avboit_segments.js +130 -0
  161. package/src/shade/renderer/trails/shaders/shader_trail_draw_args.d.ts +29 -0
  162. package/src/shade/renderer/trails/shaders/shader_trail_draw_args.d.ts.map +1 -0
  163. package/src/shade/renderer/trails/shaders/shader_trail_draw_args.js +78 -0
  164. package/src/shade/renderer/trails/shaders/shader_trail_seed.d.ts +18 -0
  165. package/src/shade/renderer/trails/shaders/shader_trail_seed.d.ts.map +1 -0
  166. package/src/shade/renderer/trails/shaders/shader_trail_seed.js +79 -0
  167. package/src/shade/renderer/trails/shaders/shader_trail_update.d.ts +20 -0
  168. package/src/shade/renderer/trails/shaders/shader_trail_update.d.ts.map +1 -0
  169. package/src/shade/renderer/trails/shaders/shader_trail_update.js +101 -0
  170. package/src/engine/graphics/ecs/trail3d/advance_trail.d.ts +0 -18
  171. package/src/engine/graphics/ecs/trail3d/advance_trail.d.ts.map +0 -1
  172. package/src/engine/graphics/ecs/trail3d/advance_trail.js +0 -42
  173. package/src/engine/graphics/ecs/trail3d/seed_trail_tube.d.ts +0 -14
  174. package/src/engine/graphics/ecs/trail3d/seed_trail_tube.d.ts.map +0 -1
  175. package/src/engine/graphics/ecs/trail3d/seed_trail_tube.js +0 -75
  176. package/src/engine/graphics/ecs/trail3d/trail_head_position.d.ts +0 -17
  177. package/src/engine/graphics/ecs/trail3d/trail_head_position.d.ts.map +0 -1
  178. package/src/engine/graphics/ecs/trail3d/trail_head_position.js +0 -19
  179. package/src/engine/graphics/trail/tube/TubeX.d.ts +0 -186
  180. package/src/engine/graphics/trail/tube/TubeX.d.ts.map +0 -1
  181. package/src/engine/graphics/trail/tube/TubeX.js +0 -575
  182. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.d.ts +0 -16
  183. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.d.ts.map +0 -1
  184. package/src/engine/graphics/trail/tube/simulator/TubeXFixedPhysicsSimulator.js +0 -34
  185. package/src/engine/graphics/trail/tube/tube_attributes_spec.d.ts +0 -27
  186. package/src/engine/graphics/trail/tube/tube_attributes_spec.d.ts.map +0 -1
  187. package/src/engine/graphics/trail/tube/tube_attributes_spec.js +0 -70
  188. package/src/engine/graphics3/trail/trail_tube_write_geometry.d.ts +0 -38
  189. package/src/engine/graphics3/trail/trail_tube_write_geometry.d.ts.map +0 -1
  190. package/src/engine/graphics3/trail/trail_tube_write_geometry.js +0 -119
@@ -0,0 +1,14 @@
1
+ export const TRAIL_PAGE_SIZE: number;
2
+ export const TRAIL_DATABASE_INITIAL_SIZE: number;
3
+ export const TRAIL_TABLE: "trails";
4
+ export const TRAIL_STATE_TABLE: "trail_state";
5
+ /**
6
+ * The trails a scene context draws: the records the CPU stages and the state the GPU integrates, two
7
+ * tables in one buffer, at the same row. Rows are handed out densely by the runtime, not keyed by
8
+ * entity, so a page holds trails rather than holes.
9
+ */
10
+ export const TRAIL_DATABASE_SPEC: GPUDatabaseDefinition;
11
+ export const TRAIL_DESCRIPTOR: import("../../buffer/table/GPUTypedTableDescriptor.js").GPUTypedTableDescriptor;
12
+ export const TRAIL_STATE_DESCRIPTOR: import("../../buffer/table/GPUTypedTableDescriptor.js").GPUTypedTableDescriptor;
13
+ import { GPUDatabaseDefinition } from "../../buffer/table/GPUDatabaseDefinition.js";
14
+ //# sourceMappingURL=TRAIL_DATABASE_SPEC.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TRAIL_DATABASE_SPEC.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/trails/data/TRAIL_DATABASE_SPEC.js"],"names":[],"mappings":"AAMA,qCAA6C;AAE7C,iDAAyD;AAEzD,mCAAoC;AAEpC,8CAA+C;AAE/C;;;;GAIG;AACH,wDAGoB;AAapB,+GAAqE;AAErE,qHAAiF;sCApC3C,6CAA6C"}
@@ -0,0 +1,38 @@
1
+ import { KILOBYTE } from "../../../../core/science/units/memory/KILOBYTE.js";
2
+ import { GPUDatabaseDefinition } from "../../buffer/table/GPUDatabaseDefinition.js";
3
+ import { SCENE_DATABASE_SPEC } from "../../scene/SCENE_DATABASE_SPEC.js";
4
+ import { TRAIL_STRUCT } from "./TRAIL_RECORD.js";
5
+ import { TRAIL_STATE_STRUCT } from "./TRAIL_STATE.js";
6
+
7
+ export const TRAIL_PAGE_SIZE = 16 * KILOBYTE;
8
+
9
+ export const TRAIL_DATABASE_INITIAL_SIZE = 64 * KILOBYTE;
10
+
11
+ export const TRAIL_TABLE = "trails";
12
+
13
+ export const TRAIL_STATE_TABLE = "trail_state";
14
+
15
+ /**
16
+ * The trails a scene context draws: the records the CPU stages and the state the GPU integrates, two
17
+ * tables in one buffer, at the same row. Rows are handed out densely by the runtime, not keyed by
18
+ * entity, so a page holds trails rather than holes.
19
+ */
20
+ export const TRAIL_DATABASE_SPEC = GPUDatabaseDefinition.from({
21
+ [TRAIL_TABLE]: TRAIL_STRUCT,
22
+ [TRAIL_STATE_TABLE]: TRAIL_STATE_STRUCT,
23
+ }, TRAIL_PAGE_SIZE);
24
+
25
+ // The transforms row of the trail's entity, where the update reads its world matrix. Held through the
26
+ // scene's rows by the trail system; it is not this database's to free.
27
+ TRAIL_DATABASE_SPEC.add_link({
28
+ table: TRAIL_TABLE,
29
+ field: 'node',
30
+ target_database: SCENE_DATABASE_SPEC,
31
+ target_table: 'transforms',
32
+ nullable: false,
33
+ owning: false,
34
+ });
35
+
36
+ export const TRAIL_DESCRIPTOR = TRAIL_DATABASE_SPEC.get(TRAIL_TABLE);
37
+
38
+ export const TRAIL_STATE_DESCRIPTOR = TRAIL_DATABASE_SPEC.get(TRAIL_STATE_TABLE);
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Write one knot into `words` (a `Uint32Array` over the pool's words) at knot index `knot`, through
3
+ * `floats`, a `Float32Array` over the same bytes. The frame goes through the CPU encoder that matches
4
+ * `decode_vertex_normal`.
5
+ *
6
+ * @param {Uint32Array} words
7
+ * @param {Float32Array} floats
8
+ * @param {number} knot
9
+ * @param {number} x
10
+ * @param {number} y
11
+ * @param {number} z
12
+ * @param {number} birth tick
13
+ * @param {ArrayLike<number>} frame `[nx, ny, nz, bx, by, bz]`, unit and orthogonal
14
+ * @param {number} thickness
15
+ * @param {number} trail row
16
+ */
17
+ export function trail_knot_write(words: Uint32Array, floats: Float32Array, knot: number, x: number, y: number, z: number, birth: number, frame: ArrayLike<number>, thickness: number, trail: number): void;
18
+ /**
19
+ * Words of one knot in the knot pool:
20
+ *
21
+ * [0..2] position f32 × 3, world space
22
+ * [3] birth u32, the tick the knot was committed at (`TRAIL_TICKS_PER_SECOND`)
23
+ * [4] normal the ring frame's first axis, through `encode_vertex_normal`
24
+ * [5] binormal the second axis, the same way
25
+ * [6] thickness f32, the tube's diameter at this knot
26
+ * [7] trail u32, the row of the trail the knot belongs to
27
+ *
28
+ * A knot stores when it was committed, not how old it is, so nothing writes it as it ages.
29
+ *
30
+ * @type {number}
31
+ */
32
+ export const TRAIL_KNOT_WORDS: number;
33
+ export const TRAIL_KNOT_BYTES: number;
34
+ export const TRAIL_KNOT_POSITION: 0;
35
+ export const TRAIL_KNOT_BIRTH: 3;
36
+ export const TRAIL_KNOT_NORMAL: 4;
37
+ export const TRAIL_KNOT_BINORMAL: 5;
38
+ export const TRAIL_KNOT_THICKNESS: 6;
39
+ export const TRAIL_KNOT_TRAIL: 7;
40
+ /**
41
+ * Trail time is counted in ticks of 2⁻¹⁶ s (about 15 µs) in a u32, which wraps every 65,536 s (18.2 h).
42
+ * An age is `(now - birth) mod 2³²`, exact while it is under the wrap; a trail never asks the age of a
43
+ * knot it has already seen fade out, so an age is only ever read while it is under `maxAge` plus one
44
+ * frame.
45
+ *
46
+ * @type {number}
47
+ */
48
+ export const TRAIL_TICKS_PER_SECOND: number;
49
+ /**
50
+ * Reading and writing knots of the pool the enclosing shader binds as `knots` (`array<u32>`, read or
51
+ * read-write) by knot address — the index of the knot in the pool, not of its first word.
52
+ *
53
+ * - `trail_knot_read(address) -> TrailKnot`
54
+ * - `trail_knot_write(address, knot)` (the binding must be read-write)
55
+ * - `trail_knot_position(address) -> vec3<f32>`, `trail_knot_birth(address) -> u32`
56
+ *
57
+ * @type {CodeChunk}
58
+ */
59
+ export const chunk_trail_knot_read: CodeChunk;
60
+ /**
61
+ * @see chunk_trail_knot_read
62
+ * @type {CodeChunk}
63
+ */
64
+ export const chunk_trail_knot_write: CodeChunk;
65
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
66
+ //# sourceMappingURL=TRAIL_KNOT.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TRAIL_KNOT.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/trails/data/TRAIL_KNOT.js"],"names":[],"mappings":"AAwCA;;;;;;;;;;;;;;;GAeG;AACH,wCAXW,WAAW,UACX,YAAY,QACZ,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,SACN,MAAM,SACN,UAAU,MAAM,CAAC,aACjB,MAAM,SACN,MAAM,QAiBhB;AAlED;;;;;;;;;;;;;GAaG;AACH,+BAFU,MAAM,CAEkB;AAElC,sCAAqD;AAErD,oCAAqC;AACrC,iCAAkC;AAClC,kCAAmC;AACnC,oCAAqC;AACrC,qCAAsC;AACtC,iCAAkC;AAElC;;;;;;;GAOG;AACH,qCAFU,MAAM,CAE4B;AAmC5C;;;;;;;;;GASG;AACH,oCAFU,SAAS,CA+CjB;AAEF;;;GAGG;AACH,qCAFU,SAAS,CAqBjB;0BAtJwB,oCAAoC"}
@@ -0,0 +1,154 @@
1
+ import { encode_normals_to_octahedral_u32 } from "../../geometry/normals/encode_normals_to_octahedral_u32.js";
2
+ import { chunk_decode_vertex_normal } from "../../shader/chunk/geometry/normal/chunk_decode_vertex_normal.js";
3
+ import { chunk_encode_vertex_normal } from "../../shader/chunk/geometry/normal/chunk_encode_vertex_normal.js";
4
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
5
+
6
+ /**
7
+ * Words of one knot in the knot pool:
8
+ *
9
+ * [0..2] position f32 × 3, world space
10
+ * [3] birth u32, the tick the knot was committed at (`TRAIL_TICKS_PER_SECOND`)
11
+ * [4] normal the ring frame's first axis, through `encode_vertex_normal`
12
+ * [5] binormal the second axis, the same way
13
+ * [6] thickness f32, the tube's diameter at this knot
14
+ * [7] trail u32, the row of the trail the knot belongs to
15
+ *
16
+ * A knot stores when it was committed, not how old it is, so nothing writes it as it ages.
17
+ *
18
+ * @type {number}
19
+ */
20
+ export const TRAIL_KNOT_WORDS = 8;
21
+
22
+ export const TRAIL_KNOT_BYTES = TRAIL_KNOT_WORDS * 4;
23
+
24
+ export const TRAIL_KNOT_POSITION = 0;
25
+ export const TRAIL_KNOT_BIRTH = 3;
26
+ export const TRAIL_KNOT_NORMAL = 4;
27
+ export const TRAIL_KNOT_BINORMAL = 5;
28
+ export const TRAIL_KNOT_THICKNESS = 6;
29
+ export const TRAIL_KNOT_TRAIL = 7;
30
+
31
+ /**
32
+ * Trail time is counted in ticks of 2⁻¹⁶ s (about 15 µs) in a u32, which wraps every 65,536 s (18.2 h).
33
+ * An age is `(now - birth) mod 2³²`, exact while it is under the wrap; a trail never asks the age of a
34
+ * knot it has already seen fade out, so an age is only ever read while it is under `maxAge` plus one
35
+ * frame.
36
+ *
37
+ * @type {number}
38
+ */
39
+ export const TRAIL_TICKS_PER_SECOND = 65536;
40
+
41
+ /**
42
+ * Write one knot into `words` (a `Uint32Array` over the pool's words) at knot index `knot`, through
43
+ * `floats`, a `Float32Array` over the same bytes. The frame goes through the CPU encoder that matches
44
+ * `decode_vertex_normal`.
45
+ *
46
+ * @param {Uint32Array} words
47
+ * @param {Float32Array} floats
48
+ * @param {number} knot
49
+ * @param {number} x
50
+ * @param {number} y
51
+ * @param {number} z
52
+ * @param {number} birth tick
53
+ * @param {ArrayLike<number>} frame `[nx, ny, nz, bx, by, bz]`, unit and orthogonal
54
+ * @param {number} thickness
55
+ * @param {number} trail row
56
+ */
57
+ export function trail_knot_write(words, floats, knot, x, y, z, birth, frame, thickness, trail) {
58
+ const base = knot * TRAIL_KNOT_WORDS;
59
+
60
+ floats[base + TRAIL_KNOT_POSITION] = x;
61
+ floats[base + TRAIL_KNOT_POSITION + 1] = y;
62
+ floats[base + TRAIL_KNOT_POSITION + 2] = z;
63
+
64
+ words[base + TRAIL_KNOT_BIRTH] = birth >>> 0;
65
+
66
+ // normal and binormal are adjacent words, so the encoder writes both in one call
67
+ encode_normals_to_octahedral_u32(words, base + TRAIL_KNOT_NORMAL, 2, frame);
68
+
69
+ floats[base + TRAIL_KNOT_THICKNESS] = thickness;
70
+
71
+ words[base + TRAIL_KNOT_TRAIL] = trail >>> 0;
72
+ }
73
+
74
+ /**
75
+ * Reading and writing knots of the pool the enclosing shader binds as `knots` (`array<u32>`, read or
76
+ * read-write) by knot address — the index of the knot in the pool, not of its first word.
77
+ *
78
+ * - `trail_knot_read(address) -> TrailKnot`
79
+ * - `trail_knot_write(address, knot)` (the binding must be read-write)
80
+ * - `trail_knot_position(address) -> vec3<f32>`, `trail_knot_birth(address) -> u32`
81
+ *
82
+ * @type {CodeChunk}
83
+ */
84
+ export const chunk_trail_knot_read = CodeChunk.from(
85
+ //language=WGSL
86
+ `
87
+ const TRAIL_KNOT_WORDS : u32 = ${TRAIL_KNOT_WORDS}u;
88
+
89
+ struct TrailKnot {
90
+ position : vec3<f32>,
91
+ birth : u32,
92
+ normal : vec3<f32>,
93
+ binormal : vec3<f32>,
94
+ thickness : f32,
95
+ trail : u32,
96
+ }
97
+
98
+ fn trail_knot_position(address : u32) -> vec3<f32> {
99
+ let base = address * TRAIL_KNOT_WORDS;
100
+
101
+ return vec3<f32>(
102
+ bitcast<f32>(knots[base + ${TRAIL_KNOT_POSITION}u]),
103
+ bitcast<f32>(knots[base + ${TRAIL_KNOT_POSITION + 1}u]),
104
+ bitcast<f32>(knots[base + ${TRAIL_KNOT_POSITION + 2}u]),
105
+ );
106
+ }
107
+
108
+ fn trail_knot_birth(address : u32) -> u32 {
109
+ return knots[address * TRAIL_KNOT_WORDS + ${TRAIL_KNOT_BIRTH}u];
110
+ }
111
+
112
+ fn trail_knot_read(address : u32) -> TrailKnot {
113
+ let base = address * TRAIL_KNOT_WORDS;
114
+
115
+ var knot : TrailKnot;
116
+
117
+ knot.position = trail_knot_position(address);
118
+ knot.birth = knots[base + ${TRAIL_KNOT_BIRTH}u];
119
+ knot.normal = decode_vertex_normal(knots[base + ${TRAIL_KNOT_NORMAL}u]);
120
+ knot.binormal = decode_vertex_normal(knots[base + ${TRAIL_KNOT_BINORMAL}u]);
121
+ knot.thickness = bitcast<f32>(knots[base + ${TRAIL_KNOT_THICKNESS}u]);
122
+ knot.trail = knots[base + ${TRAIL_KNOT_TRAIL}u];
123
+
124
+ return knot;
125
+ }
126
+ `, [
127
+ chunk_decode_vertex_normal,
128
+ ]
129
+ );
130
+
131
+ /**
132
+ * @see chunk_trail_knot_read
133
+ * @type {CodeChunk}
134
+ */
135
+ export const chunk_trail_knot_write = CodeChunk.from(
136
+ //language=WGSL
137
+ `
138
+ fn trail_knot_write(address : u32, knot : TrailKnot) {
139
+ let base = address * TRAIL_KNOT_WORDS;
140
+
141
+ knots[base + ${TRAIL_KNOT_POSITION}u] = bitcast<u32>(knot.position.x);
142
+ knots[base + ${TRAIL_KNOT_POSITION + 1}u] = bitcast<u32>(knot.position.y);
143
+ knots[base + ${TRAIL_KNOT_POSITION + 2}u] = bitcast<u32>(knot.position.z);
144
+ knots[base + ${TRAIL_KNOT_BIRTH}u] = knot.birth;
145
+ knots[base + ${TRAIL_KNOT_NORMAL}u] = encode_vertex_normal(knot.normal);
146
+ knots[base + ${TRAIL_KNOT_BINORMAL}u] = encode_vertex_normal(knot.binormal);
147
+ knots[base + ${TRAIL_KNOT_THICKNESS}u] = bitcast<u32>(knot.thickness);
148
+ knots[base + ${TRAIL_KNOT_TRAIL}u] = knot.trail;
149
+ }
150
+ `, [
151
+ chunk_trail_knot_read,
152
+ chunk_encode_vertex_normal,
153
+ ]
154
+ );
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Bits of {@link TRAIL_STRUCT }`.flags`.
3
+ */
4
+ export type TRAIL_FLAG = number;
5
+ export namespace TRAIL_FLAG {
6
+ let SPAWNING: number;
7
+ let DISTANCE: number;
8
+ let AUTHORED: number;
9
+ let WARMUP: number;
10
+ let TAIL_VISIBLE: number;
11
+ let RESEED: number;
12
+ }
13
+ /**
14
+ * One trail, as the CPU stages it: where it is, how long its knot run is and what it looks like. The
15
+ * GPU never writes it; what the GPU integrates lives in `TRAIL_STATE_STRUCT`, at the same row.
16
+ */
17
+ export const TRAIL_STRUCT: WebGPUStruct;
18
+ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
19
+ //# sourceMappingURL=TRAIL_RECORD.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TRAIL_RECORD.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/trails/data/TRAIL_RECORD.js"],"names":[],"mappings":";;;yBAOU,MAAM;;;;;;;;;AAuBhB;;;GAGG;AACH,wCAiC2B;6BAlEE,mCAAmC"}
@@ -0,0 +1,68 @@
1
+ import { f32, u32, vec3f, vec4f } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
+ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
3
+
4
+ /**
5
+ * Bits of {@link TRAIL_STRUCT}`.flags`.
6
+ *
7
+ * @readonly
8
+ * @enum {number}
9
+ */
10
+ export const TRAIL_FLAG = {
11
+ /** The head follows the entity and commits knots; clear for a trail that only ages where it lies. */
12
+ SPAWNING: 1,
13
+ /** Knots are committed by distance travelled (`spawn_distance`) rather than by time (`commit_ticks`). */
14
+ DISTANCE: 2,
15
+ /**
16
+ * The knots were laid down by the CPU (a stroke), with ages that need not grow away from the head,
17
+ * so every knot is a candidate for drawing rather than the run the live count covers.
18
+ */
19
+ AUTHORED: 4,
20
+ /** The head is born `maxAge - t` old during the trail's first `maxAge` seconds, so the trail fades in. */
21
+ WARMUP: 8,
22
+ /** The fade is above zero at the end of a knot's life, so a knot past `maxAge` is still drawn. */
23
+ TAIL_VISIBLE: 16,
24
+ /**
25
+ * The pending seed is a `clear()`: it expires every knot and collapses them onto the head, but keeps
26
+ * the trail's birth and the knots' frames. Without it a seed is a build: everything starts over.
27
+ */
28
+ RESEED: 32,
29
+ };
30
+
31
+ /**
32
+ * One trail, as the CPU stages it: where it is, how long its knot run is and what it looks like. The
33
+ * GPU never writes it; what the GPU integrates lives in `TRAIL_STATE_STRUCT`, at the same row.
34
+ */
35
+ export const TRAIL_STRUCT = WebGPUStruct.from({
36
+ /** the `transforms` row of the trail's entity, whose world matrix the head follows */
37
+ node: u32,
38
+ /** the first knot of the trail's run in the knot pool */
39
+ knot_base: u32,
40
+ /** knots in the run: a ring, head to tail */
41
+ knot_count: u32,
42
+ /** radial segments around the tube; the trail's draw class is the one for this count */
43
+ radial: u32,
44
+ /** {@link TRAIL_FLAG} bits */
45
+ flags: u32,
46
+ /** moved by the CPU for every seed it asks for; a state that has not seen it is seeded */
47
+ seed_epoch: u32,
48
+ /** ticks between commits in time mode: `maxAge / knot_count`, rounded down */
49
+ commit_ticks: u32,
50
+ /** `maxAge` in ticks: an age at or past it has faded out */
51
+ max_age_ticks: u32,
52
+ /** `maxAge` in seconds, what the fade's time is a fraction of */
53
+ max_age: f32,
54
+ /** tube diameter, given to each knot the head writes */
55
+ width: f32,
56
+ /** distance the head travels between commits in distance mode */
57
+ spawn_distance: f32,
58
+ /** the first key of the trail's fade curve in the fade key buffer */
59
+ fade_first: u32,
60
+ /** keys in the fade curve */
61
+ fade_count: u32,
62
+ /** the index of the trail's radial class: which list a visible segment of it is drawn from */
63
+ draw_class: u32,
64
+ /** where the head sits in the entity's local frame */
65
+ offset: vec3f,
66
+ /** linear RGB, unbounded, and the trail's base opacity, which the fade scales */
67
+ color: vec4f,
68
+ }, "Trail3DRecord").pack();
@@ -0,0 +1,18 @@
1
+ /**
2
+ * What the GPU integrates for a trail, at the same row as its `TRAIL_STRUCT`.
3
+ *
4
+ * The CPU writes a state row twice: when it claims the row, and when it lets the row go. In between
5
+ * only the GPU writes it — the seed pass when the record's `seed_epoch` moves, the update pass every
6
+ * frame. A CPU-authored trail is the exception that proves it: its knots are laid down by the CPU, so
7
+ * the CPU writes its whole starting state at claim, seeded already.
8
+ */
9
+ export const TRAIL_STATE_STRUCT: WebGPUStruct;
10
+ /**
11
+ * The state of a row claimed for a trail the GPU seeds: an epoch no record carries, so the first frame
12
+ * that sees the row seeds it.
13
+ *
14
+ * @type {Object}
15
+ */
16
+ export const TRAIL_STATE_UNSEEDED: any;
17
+ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
18
+ //# sourceMappingURL=TRAIL_STATE.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TRAIL_STATE.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/trails/data/TRAIL_STATE.js"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,8CAgBmB;AAEnB;;;;;GAKG;AACH,uCAOG;6BAzC0B,mCAAmC"}
@@ -0,0 +1,43 @@
1
+ import { f32, u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
+ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
3
+
4
+ /**
5
+ * What the GPU integrates for a trail, at the same row as its `TRAIL_STRUCT`.
6
+ *
7
+ * The CPU writes a state row twice: when it claims the row, and when it lets the row go. In between
8
+ * only the GPU writes it — the seed pass when the record's `seed_epoch` moves, the update pass every
9
+ * frame. A CPU-authored trail is the exception that proves it: its knots are laid down by the CPU, so
10
+ * the CPU writes its whole starting state at claim, seeded already.
11
+ */
12
+ export const TRAIL_STATE_STRUCT = WebGPUStruct.from({
13
+ /** the head's slot in the run; the predecessor, older by one knot, is the next slot round */
14
+ head: u32,
15
+ /**
16
+ * Knots from the head that can still be visible. Only these are ever asked their age, which is what
17
+ * keeps a wrapped tick count from reading as young.
18
+ */
19
+ live: u32,
20
+ /** tick of the last commit, or of the seed */
21
+ last_commit: u32,
22
+ /** tick the trail was built at: the warm-up runs on the time since */
23
+ birth: u32,
24
+ /** the `seed_epoch` this state was last seeded for */
25
+ seeded_epoch: u32,
26
+ /** distance the head has travelled since the last commit */
27
+ distance: f32,
28
+ }, "Trail3DState");
29
+
30
+ /**
31
+ * The state of a row claimed for a trail the GPU seeds: an epoch no record carries, so the first frame
32
+ * that sees the row seeds it.
33
+ *
34
+ * @type {Object}
35
+ */
36
+ export const TRAIL_STATE_UNSEEDED = Object.freeze({
37
+ head: 0,
38
+ live: 0,
39
+ last_commit: 0,
40
+ birth: 0,
41
+ seeded_epoch: 0,
42
+ distance: 0,
43
+ });
@@ -0,0 +1,58 @@
1
+ /**
2
+ * @typedef {Object} TrailSimulationHandles
3
+ * @property {number} trail_database graph handle of the trail and state tables, after the update
4
+ * @property {number} knots graph handle of the knot pool, after the update
5
+ * @property {number} fade_keys graph handle of the fade key buffer
6
+ * @property {number} segment_sums graph handle of the inclusive sums of live segments over the trail rows
7
+ * @property {number} segments_command graph handle of the dispatch, a thread per live segment, folded
8
+ * @property {number} capacity rows the sums cover
9
+ */
10
+ /**
11
+ * Record one frame of the trails, view-independent, once per frame: the seeds asked for, the update of
12
+ * every trail, the scan of their live segments and the dispatch the per-view passes take from it.
13
+ *
14
+ * Call after the hierarchy has composed this frame's matrices — the update reads them — and after the
15
+ * runtime's upload, so the records are on the device.
16
+ *
17
+ * @param {object} params
18
+ * @param {import("../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} params.graph
19
+ * @param {number} params.scene_database graph handle of the scene database
20
+ * @param {import("./GPUTrailSystem.js").GPUTrailSystem} params.runtime
21
+ * @param {GPUBuffer} params.fade_keys the fade key buffer, as the upload left it
22
+ * @param {Uint32Array} params.seeds rows to seed this frame
23
+ * @returns {TrailSimulationHandles}
24
+ */
25
+ export function graph_trails_simulate({ graph, scene_database, runtime, fade_keys, seeds }: {
26
+ graph: import("../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
27
+ scene_database: number;
28
+ runtime: import("./GPUTrailSystem.js").GPUTrailSystem;
29
+ fade_keys: GPUBuffer;
30
+ seeds: Uint32Array;
31
+ }): TrailSimulationHandles;
32
+ export type TrailSimulationHandles = {
33
+ /**
34
+ * graph handle of the trail and state tables, after the update
35
+ */
36
+ trail_database: number;
37
+ /**
38
+ * graph handle of the knot pool, after the update
39
+ */
40
+ knots: number;
41
+ /**
42
+ * graph handle of the fade key buffer
43
+ */
44
+ fade_keys: number;
45
+ /**
46
+ * graph handle of the inclusive sums of live segments over the trail rows
47
+ */
48
+ segment_sums: number;
49
+ /**
50
+ * graph handle of the dispatch, a thread per live segment, folded
51
+ */
52
+ segments_command: number;
53
+ /**
54
+ * rows the sums cover
55
+ */
56
+ capacity: number;
57
+ };
58
+ //# sourceMappingURL=graph_trails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph_trails.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/trails/graph_trails.js"],"names":[],"mappings":"AAgBA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;;;GAcG;AACH;IAPkG,KAAK,EAA5F,OAAO,2DAA2D,EAAE,UAAU;IAC/D,cAAc,EAA7B,MAAM;IAC+C,OAAO,EAA5D,OAAO,qBAAqB,EAAE,cAAc;IAC1B,SAAS;IACP,KAAK,EAAzB,WAAW;IACT,sBAAsB,CAwElC;;;;;oBA7Fa,MAAM;;;;WACN,MAAM;;;;eACN,MAAM;;;;kBACN,MAAM;;;;sBACN,MAAM;;;;cACN,MAAM"}
@@ -0,0 +1,155 @@
1
+ import { align_4 } from "../../../core/binary/align_4.js";
2
+ import { assert } from "../../../core/assert.js";
3
+ import { BufferResourceDescriptor } from "../../device/graph/BufferResourceDescriptor.js";
4
+ import { INDIRECT_COMPUTE_COMMAND_DESCRIPTOR } from "../gpu_primitive/indirect/IndirectComputeCommandBuildPass.js";
5
+ import {
6
+ graph_prefix_scan_csdldf,
7
+ prefix_scan_csdldf_output_descriptor
8
+ } from "../gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js";
9
+ import { PREFIX_SCAN_CSDLDF_HEADER_WORDS } from "../gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.js";
10
+ import { shader_prefix_sum_to_command } from "../rasterize/expand/mesh/shader_prefix_sum_to_command.js";
11
+ import { graph_compute_pass } from "../shader/graph/compute/graph_compute_pass.js";
12
+ import { graph_create_buffer } from "../shader/graph/graph_create_buffer.js";
13
+ import { graph_import_buffer } from "../shader/graph/graph_import_buffer.js";
14
+ import { shader_trail_seed } from "./shaders/shader_trail_seed.js";
15
+ import { shader_trail_update, TRAIL_UPDATE_WORKGROUP_SIZE } from "./shaders/shader_trail_update.js";
16
+
17
+ /**
18
+ * @typedef {Object} TrailSimulationHandles
19
+ * @property {number} trail_database graph handle of the trail and state tables, after the update
20
+ * @property {number} knots graph handle of the knot pool, after the update
21
+ * @property {number} fade_keys graph handle of the fade key buffer
22
+ * @property {number} segment_sums graph handle of the inclusive sums of live segments over the trail rows
23
+ * @property {number} segments_command graph handle of the dispatch, a thread per live segment, folded
24
+ * @property {number} capacity rows the sums cover
25
+ */
26
+
27
+ /**
28
+ * Record one frame of the trails, view-independent, once per frame: the seeds asked for, the update of
29
+ * every trail, the scan of their live segments and the dispatch the per-view passes take from it.
30
+ *
31
+ * Call after the hierarchy has composed this frame's matrices — the update reads them — and after the
32
+ * runtime's upload, so the records are on the device.
33
+ *
34
+ * @param {object} params
35
+ * @param {import("../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} params.graph
36
+ * @param {number} params.scene_database graph handle of the scene database
37
+ * @param {import("./GPUTrailSystem.js").GPUTrailSystem} params.runtime
38
+ * @param {GPUBuffer} params.fade_keys the fade key buffer, as the upload left it
39
+ * @param {Uint32Array} params.seeds rows to seed this frame
40
+ * @returns {TrailSimulationHandles}
41
+ */
42
+ export function graph_trails_simulate({ graph, scene_database, runtime, fade_keys, seeds }) {
43
+ assert.isNonNegativeInteger(scene_database, "scene_database");
44
+
45
+ const now = runtime.now;
46
+ const table = runtime.table;
47
+
48
+ // Two tables in one buffer, and the knots; each pass that writes them renames the handle the next
49
+ // reader takes.
50
+ let trail_database = graph_import_buffer(graph, runtime.database.buffer, "trails/database");
51
+ let knots = graph_import_buffer(graph, runtime.knots.buffer, "trails/knots");
52
+ const gr_fade_keys = graph_import_buffer(graph, fade_keys, "trails/fade_keys");
53
+
54
+ if (seeds.length > 0) {
55
+ const out = graph_trail_seed({ graph, scene_database, trail_database, knots, seeds, now });
56
+
57
+ trail_database = out.trail_database;
58
+ knots = out.knots;
59
+ }
60
+
61
+ const capacity = Math.max(1, table.element_capacity);
62
+
63
+ // the counts are cleared whole: the update writes only the rows it visits
64
+ const count_bytes = (PREFIX_SCAN_CSDLDF_HEADER_WORDS + align_4(capacity)) * Uint32Array.BYTES_PER_ELEMENT;
65
+
66
+ let live_segments = graph_create_buffer(graph, "trails/live_segments", BufferResourceDescriptor.from(
67
+ count_bytes,
68
+ GPUBufferUsage.STORAGE,
69
+ 0, count_bytes,
70
+ ));
71
+
72
+ const group_count = table.dispatch_group_count(TRAIL_UPDATE_WORKGROUP_SIZE);
73
+
74
+ // a table with no pages has nothing to visit: the cleared counts scan to zero
75
+ if (group_count > 0) {
76
+ const out = graph_compute_pass({
77
+ graph,
78
+ shader: shader_trail_update,
79
+ bindings: {
80
+ trail_database,
81
+ scene_database,
82
+ knots,
83
+ live_segments,
84
+ settings: { now, capacity },
85
+ },
86
+ group_count: [group_count, 1, 1],
87
+ });
88
+
89
+ trail_database = out.trail_database;
90
+ knots = out.knots;
91
+ live_segments = out.live_segments;
92
+ }
93
+
94
+ const segment_sums = graph_prefix_scan_csdldf({
95
+ graph,
96
+ input: live_segments,
97
+ output: graph_create_buffer(graph, "trails/segment_sums", prefix_scan_csdldf_output_descriptor(capacity)),
98
+ element_max_count: capacity,
99
+ });
100
+
101
+ const segments_command = graph_compute_pass({
102
+ graph,
103
+ shader: shader_prefix_sum_to_command,
104
+ bindings: {
105
+ prefix_sums: segment_sums,
106
+ command: graph_create_buffer(graph, "trails/segments_command", INDIRECT_COMPUTE_COMMAND_DESCRIPTOR),
107
+ },
108
+ group_count: [1, 1, 1],
109
+ }).command;
110
+
111
+ return { trail_database, knots, fade_keys: gr_fade_keys, segment_sums, segments_command, capacity };
112
+ }
113
+
114
+ /**
115
+ * The seed pass: a workgroup per row of `seeds`, the list uploaded with the pass.
116
+ *
117
+ * @param {object} params
118
+ * @param {import("../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} params.graph
119
+ * @param {number} params.scene_database
120
+ * @param {number} params.trail_database
121
+ * @param {number} params.knots
122
+ * @param {Uint32Array} params.seeds
123
+ * @param {number} params.now
124
+ * @returns {{trail_database: number, knots: number}}
125
+ */
126
+ function graph_trail_seed({ graph, scene_database, trail_database, knots, seeds, now }) {
127
+ function execute(data, resources, context) {
128
+ const encoder = context.encoder;
129
+
130
+ shader_trail_seed.dispatch({
131
+ encoder,
132
+ bindings: {
133
+ trail_database: resources.get(data.trail_database),
134
+ scene_database: resources.get(data.scene_database),
135
+ knots: resources.get(data.knots),
136
+ seeds: encoder.allocateTransientBufferAndLoad(seeds.buffer, GPUBufferUsage.STORAGE, seeds.byteOffset, seeds.byteLength),
137
+ settings: { now },
138
+ },
139
+ group_count_x: seeds.length,
140
+ group_count_y: 1,
141
+ group_count_z: 1,
142
+ });
143
+ }
144
+
145
+ const pass_data = {};
146
+ const pass = graph.add("Trail Seed", pass_data, execute);
147
+
148
+ pass_data.scene_database = pass.read(scene_database);
149
+ pass.read(trail_database);
150
+ pass_data.trail_database = pass.write(trail_database);
151
+ pass.read(knots);
152
+ pass_data.knots = pass.write(knots);
153
+
154
+ return { trail_database: pass_data.trail_database, knots: pass_data.knots };
155
+ }