@woosh/meep-engine 3.17.2 → 3.18.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/editor/actions/concrete/ComponentAddAction.d.ts +1 -0
  2. package/editor/actions/concrete/ComponentAddAction.d.ts.map +1 -1
  3. package/editor/actions/concrete/ComponentAddAction.js +4 -0
  4. package/editor/actions/concrete/ComponentRemoveAction.d.ts +1 -0
  5. package/editor/actions/concrete/ComponentRemoveAction.d.ts.map +1 -1
  6. package/editor/actions/concrete/ComponentRemoveAction.js +4 -0
  7. package/editor/actions/concrete/EntityCreateAction.d.ts +1 -0
  8. package/editor/actions/concrete/EntityCreateAction.d.ts.map +1 -1
  9. package/editor/actions/concrete/EntityCreateAction.js +7 -0
  10. package/editor/actions/concrete/EntityRemoveAction.d.ts +1 -0
  11. package/editor/actions/concrete/EntityRemoveAction.d.ts.map +1 -1
  12. package/editor/actions/concrete/EntityRemoveAction.js +4 -0
  13. package/editor/actions/concrete/PatchTerrainHeightAction.d.ts +10 -0
  14. package/editor/actions/concrete/PatchTerrainHeightAction.d.ts.map +1 -1
  15. package/editor/actions/concrete/PatchTerrainHeightAction.js +107 -85
  16. package/editor/actions/concrete/TransformModifyAction.d.ts +1 -0
  17. package/editor/actions/concrete/TransformModifyAction.d.ts.map +1 -1
  18. package/editor/actions/concrete/TransformModifyAction.js +4 -0
  19. package/editor/particles/effect/ParticleEffectDocument.d.ts.map +1 -1
  20. package/editor/particles/effect/ParticleEffectDocument.js +10 -6
  21. package/editor/particles/effect/ParticleReferenceSimulation.d.ts.map +1 -1
  22. package/editor/particles/effect/ParticleReferenceSimulation.js +98 -4
  23. package/editor/particles/effect/make_starter_particle_effect.d.ts.map +1 -1
  24. package/editor/particles/effect/make_starter_particle_effect.js +0 -2
  25. package/editor/tools/engine/ToolEngine.d.ts +30 -0
  26. package/editor/tools/engine/ToolEngine.d.ts.map +1 -1
  27. package/editor/tools/engine/ToolEngine.js +257 -188
  28. package/editor/view/ecs/EntityList.d.ts.map +1 -1
  29. package/editor/view/ecs/EntityList.js +6 -5
  30. package/editor/view/particles/effect/ParticleEmitterInspectorView.d.ts.map +1 -1
  31. package/editor/view/particles/effect/ParticleEmitterInspectorView.js +17 -9
  32. package/package.json +1 -1
  33. package/src/CODEC_LAYOUT_VERIFICATION.md +1 -2
  34. package/src/core/binary/meshopt/MESHOPT_VERTEX_BLOCK.d.ts +56 -0
  35. package/src/core/binary/meshopt/MESHOPT_VERTEX_BLOCK.d.ts.map +1 -0
  36. package/src/core/binary/meshopt/MESHOPT_VERTEX_BLOCK.js +73 -0
  37. package/src/core/binary/meshopt/meshopt_decode_vertex_buffer.d.ts.map +1 -1
  38. package/src/core/binary/meshopt/meshopt_decode_vertex_buffer.js +18 -63
  39. package/src/core/binary/meshopt/meshopt_encode_byte_group.d.ts +53 -0
  40. package/src/core/binary/meshopt/meshopt_encode_byte_group.d.ts.map +1 -0
  41. package/src/core/binary/meshopt/meshopt_encode_byte_group.js +140 -0
  42. package/src/core/binary/meshopt/meshopt_encode_data_block.d.ts +32 -0
  43. package/src/core/binary/meshopt/meshopt_encode_data_block.d.ts.map +1 -0
  44. package/src/core/binary/meshopt/meshopt_encode_data_block.js +77 -0
  45. package/src/core/binary/meshopt/meshopt_encode_index_sequence.d.ts +46 -0
  46. package/src/core/binary/meshopt/meshopt_encode_index_sequence.d.ts.map +1 -0
  47. package/src/core/binary/meshopt/meshopt_encode_index_sequence.js +146 -0
  48. package/src/core/binary/meshopt/meshopt_encode_vertex_buffer.d.ts +40 -0
  49. package/src/core/binary/meshopt/meshopt_encode_vertex_buffer.d.ts.map +1 -0
  50. package/src/core/binary/meshopt/meshopt_encode_vertex_buffer.js +700 -0
  51. package/src/core/binary/meshopt/meshopt_write_uint_var.d.ts +24 -0
  52. package/src/core/binary/meshopt/meshopt_write_uint_var.d.ts.map +1 -0
  53. package/src/core/binary/meshopt/meshopt_write_uint_var.js +39 -0
  54. package/src/core/math/random/seededRandom_Mulberry32.d.ts.map +1 -1
  55. package/src/core/math/random/seededRandom_Mulberry32.js +4 -2
  56. package/src/core/process/undo/Action.d.ts +19 -0
  57. package/src/core/process/undo/Action.d.ts.map +1 -1
  58. package/src/core/process/undo/Action.js +17 -0
  59. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +78 -0
  60. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -0
  61. package/src/engine/graphics3/GPUParticleEmitterSystem.js +310 -0
  62. package/src/engine/graphics3/GraphicsEngine.d.ts +17 -0
  63. package/src/engine/graphics3/GraphicsEngine.d.ts.map +1 -1
  64. package/src/engine/graphics3/GraphicsEngine.js +30 -10
  65. package/src/engine/graphics3/particles/particle_gpu_records.d.ts.map +1 -1
  66. package/src/engine/graphics3/particles/particle_gpu_records.js +0 -2
  67. package/src/engine/interpolation/InterpolationSystem.d.ts +7 -0
  68. package/src/engine/interpolation/InterpolationSystem.d.ts.map +1 -1
  69. package/src/engine/interpolation/InterpolationSystem.js +10 -0
  70. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  71. package/src/engine/network/NetworkSession.js +14 -34
  72. package/src/engine/network/time/RenderPlayout.d.ts +76 -0
  73. package/src/engine/network/time/RenderPlayout.d.ts.map +1 -0
  74. package/src/engine/network/time/RenderPlayout.js +163 -0
  75. package/src/engine/network/transport/adapters/WebSocketTransport.d.ts.map +1 -1
  76. package/src/engine/network/transport/adapters/WebSocketTransport.js +11 -4
  77. package/src/engine/physics/ecs/PhysicsSystem.d.ts +4 -12
  78. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  79. package/src/engine/physics/ecs/PhysicsSystem.js +39 -13
  80. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  81. package/src/engine/sound/simulation/core/VolumeField.d.ts.map +1 -1
  82. package/src/engine/sound/simulation/core/VolumeField.js +4 -1
  83. package/src/format/scene/gltf/MESHOPT_COMPRESSION_PLAN.md +23 -2
  84. package/src/shade/playground/particle_system/README.md +139 -139
  85. package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
  86. package/src/shade/playground/particle_system/particle_prototype.js +0 -2
  87. package/src/shade/playground/particle_system/particle_scene.d.ts +6 -9
  88. package/src/shade/playground/particle_system/particle_scene.d.ts.map +1 -1
  89. package/src/shade/playground/particle_system/particle_scene.js +6 -13
  90. package/src/shade/playground/ssr_reprojection/README.md +103 -0
  91. package/src/shade/playground/ssr_reprojection/SpatialFilterProbe.d.ts +17 -0
  92. package/src/shade/playground/ssr_reprojection/SpatialFilterProbe.d.ts.map +1 -0
  93. package/src/shade/playground/ssr_reprojection/SpatialFilterProbe.js +68 -0
  94. package/src/shade/playground/ssr_reprojection/index.html +79 -0
  95. package/src/shade/playground/ssr_reprojection/main.d.ts +2 -0
  96. package/src/shade/playground/ssr_reprojection/main.d.ts.map +1 -0
  97. package/src/shade/playground/ssr_reprojection/main.js +245 -0
  98. package/src/shade/playground/ssr_reprojection/scene.d.ts +18 -0
  99. package/src/shade/playground/ssr_reprojection/scene.d.ts.map +1 -0
  100. package/src/shade/playground/ssr_reprojection/scene.js +51 -0
  101. package/src/shade/renderer/Renderer.d.ts +2 -23
  102. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  103. package/src/shade/renderer/Renderer.js +185 -218
  104. package/src/shade/renderer/animation/GPUAnimationManager.d.ts +5 -8
  105. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  106. package/src/shade/renderer/animation/GPUAnimationManager.js +12 -12
  107. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts.map +1 -1
  108. package/src/shade/renderer/buffer/table/GPUTypedTable.js +6 -0
  109. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts.map +1 -1
  110. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +7 -0
  111. package/src/shade/renderer/global_illumination/brick4/gpu/draw/chunk_brick4_sample_specular.d.ts +4 -0
  112. package/src/shade/renderer/global_illumination/brick4/gpu/draw/chunk_brick4_sample_specular.d.ts.map +1 -0
  113. package/src/shade/renderer/global_illumination/brick4/gpu/draw/chunk_brick4_sample_specular.js +51 -0
  114. package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_specular.d.ts.map +1 -1
  115. package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_specular.js +5 -35
  116. package/src/shade/renderer/particles/DESIGN.md +703 -514
  117. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +16 -4
  118. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  119. package/src/shade/renderer/particles/GPUParticleSystem.js +1189 -991
  120. package/src/shade/renderer/particles/ParticleConstants.d.ts +64 -0
  121. package/src/shade/renderer/particles/ParticleConstants.d.ts.map +1 -1
  122. package/src/shade/renderer/particles/ParticleConstants.js +71 -0
  123. package/src/shade/renderer/particles/bounds/chunk_particle_bounds.d.ts +57 -0
  124. package/src/shade/renderer/particles/bounds/chunk_particle_bounds.d.ts.map +1 -0
  125. package/src/shade/renderer/particles/bounds/chunk_particle_bounds.js +181 -0
  126. package/src/shade/renderer/particles/bounds/chunk_particle_bounds_unknown.d.ts +7 -0
  127. package/src/shade/renderer/particles/bounds/chunk_particle_bounds_unknown.d.ts.map +1 -0
  128. package/src/shade/renderer/particles/bounds/chunk_particle_bounds_unknown.js +12 -0
  129. package/src/shade/renderer/particles/bounds/graph_particle_bounds.d.ts +33 -0
  130. package/src/shade/renderer/particles/bounds/graph_particle_bounds.d.ts.map +1 -0
  131. package/src/shade/renderer/particles/bounds/graph_particle_bounds.js +67 -0
  132. package/src/shade/renderer/particles/bounds/shader_particle_bounds.d.ts +40 -0
  133. package/src/shade/renderer/particles/bounds/shader_particle_bounds.d.ts.map +1 -0
  134. package/src/shade/renderer/particles/bounds/shader_particle_bounds.js +187 -0
  135. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts +15 -2
  136. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts.map +1 -1
  137. package/src/shade/renderer/particles/coherence/graph_particle_bucket.js +14 -8
  138. package/src/shade/renderer/particles/data/PARTICLE_COUNTERS.d.ts +58 -4
  139. package/src/shade/renderer/particles/data/PARTICLE_COUNTERS.d.ts.map +1 -1
  140. package/src/shade/renderer/particles/data/PARTICLE_COUNTERS.js +79 -4
  141. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STATE.d.ts +23 -1
  142. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STATE.d.ts.map +1 -1
  143. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STATE.js +35 -2
  144. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts +4 -2
  145. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
  146. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +5 -8
  147. package/src/shade/renderer/particles/data/particle_emitter_record.d.ts.map +1 -1
  148. package/src/shade/renderer/particles/data/particle_emitter_record.js +0 -6
  149. package/src/shade/renderer/particles/graph_particles.d.ts +25 -3
  150. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  151. package/src/shade/renderer/particles/graph_particles.js +108 -31
  152. package/src/shade/renderer/particles/graph_particles_avboit.d.ts +6 -4
  153. package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
  154. package/src/shade/renderer/particles/graph_particles_avboit.js +5 -5
  155. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts +5 -0
  156. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts.map +1 -1
  157. package/src/shade/renderer/particles/runtime/EmitterRegistry.js +27 -6
  158. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts +4 -0
  159. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts.map +1 -1
  160. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.js +6 -1
  161. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +35 -27
  162. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
  163. package/src/shade/renderer/particles/runtime/ParticleEmitter.js +424 -425
  164. package/src/shade/renderer/particles/shaders/chunk_particle_emitter_warmup.d.ts +20 -0
  165. package/src/shade/renderer/particles/shaders/chunk_particle_emitter_warmup.d.ts.map +1 -0
  166. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts +4 -0
  167. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts.map +1 -1
  168. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.js +38 -2
  169. package/src/shade/renderer/particles/shaders/chunk_particle_spawn_budget.d.ts +22 -0
  170. package/src/shade/renderer/particles/shaders/chunk_particle_spawn_budget.d.ts.map +1 -0
  171. package/src/shade/renderer/particles/shaders/chunk_particle_spawn_budget.js +42 -0
  172. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js +1 -1
  173. package/src/shade/renderer/particles/shaders/shader_particle_avboit_occupancy.d.ts.map +1 -1
  174. package/src/shade/renderer/particles/shaders/shader_particle_avboit_occupancy.js +53 -22
  175. package/src/shade/renderer/particles/shaders/shader_particle_emitter_tick.d.ts.map +1 -1
  176. package/src/shade/renderer/particles/shaders/shader_particle_emitter_tick.js +213 -216
  177. package/src/shade/renderer/particles/shaders/shader_particle_reclaim.d.ts +50 -0
  178. package/src/shade/renderer/particles/shaders/shader_particle_reclaim.d.ts.map +1 -0
  179. package/src/shade/renderer/particles/shaders/shader_particle_render.js +1 -1
  180. package/src/shade/renderer/particles/warmup/chunk_particle_warmup_step.d.ts +36 -0
  181. package/src/shade/renderer/particles/warmup/chunk_particle_warmup_step.d.ts.map +1 -0
  182. package/src/shade/renderer/particles/warmup/chunk_particle_warmup_step.js +102 -0
  183. package/src/shade/renderer/particles/warmup/graph_particle_warmup.d.ts +102 -0
  184. package/src/shade/renderer/particles/warmup/graph_particle_warmup.d.ts.map +1 -0
  185. package/src/shade/renderer/particles/warmup/graph_particle_warmup.js +329 -0
  186. package/src/shade/renderer/particles/warmup/shader_particle_warmup.d.ts +112 -0
  187. package/src/shade/renderer/particles/warmup/shader_particle_warmup.d.ts.map +1 -0
  188. package/src/shade/renderer/particles/warmup/shader_particle_warmup.js +318 -0
  189. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance.d.ts +35 -0
  190. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance.d.ts.map +1 -0
  191. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance.js +108 -0
  192. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.d.ts +3 -0
  193. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.d.ts.map +1 -0
  194. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.js +70 -0
  195. package/src/shade/renderer/particles/warmup/warmup_schedule.d.ts +62 -0
  196. package/src/shade/renderer/particles/warmup/warmup_schedule.d.ts.map +1 -0
  197. package/src/shade/renderer/particles/warmup/warmup_schedule.js +55 -0
  198. package/src/shade/renderer/postprocess/PostProcess.d.ts.map +1 -1
  199. package/src/shade/renderer/postprocess/PostProcess.js +2 -1
  200. package/src/shade/renderer/postprocess/ssr/REPROJECTION_PROPOSAL.md +286 -0
  201. package/src/shade/renderer/postprocess/ssr/SSR.d.ts +57 -21
  202. package/src/shade/renderer/postprocess/ssr/SSR.d.ts.map +1 -1
  203. package/src/shade/renderer/postprocess/ssr/SSR.js +230 -129
  204. package/src/shade/renderer/postprocess/ssr/SSRReprojectionMode.d.ts +11 -0
  205. package/src/shade/renderer/postprocess/ssr/SSRReprojectionMode.d.ts.map +1 -0
  206. package/src/shade/renderer/postprocess/ssr/SSRReprojectionMode.js +6 -0
  207. package/src/shade/renderer/postprocess/ssr/chunk_ssr_metadata.d.ts +4 -0
  208. package/src/shade/renderer/postprocess/ssr/chunk_ssr_metadata.d.ts.map +1 -0
  209. package/src/shade/renderer/postprocess/ssr/chunk_ssr_metadata.js +32 -0
  210. package/src/shade/renderer/postprocess/ssr/chunk_ssr_spatial_variance.d.ts +4 -0
  211. package/src/shade/renderer/postprocess/ssr/chunk_ssr_spatial_variance.d.ts.map +1 -0
  212. package/src/shade/renderer/postprocess/ssr/chunk_ssr_spatial_variance.js +41 -0
  213. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.d.ts +3 -0
  214. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.d.ts.map +1 -0
  215. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.js +30 -0
  216. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_sample_history.d.ts +4 -0
  217. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_sample_history.d.ts.map +1 -0
  218. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_sample_history.js +70 -0
  219. package/src/shade/renderer/postprocess/ssr/resolve/build_ssr_resolve_shader.d.ts +21 -0
  220. package/src/shade/renderer/postprocess/ssr/resolve/build_ssr_resolve_shader.d.ts.map +1 -0
  221. package/src/shade/renderer/postprocess/ssr/resolve/build_ssr_resolve_shader.js +363 -0
  222. package/src/shade/renderer/postprocess/ssr/resolve/chunk_get_neighbour_weight.js +1 -1
  223. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_Brick4.d.ts +2 -0
  224. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_Brick4.d.ts.map +1 -0
  225. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_Brick4.js +24 -0
  226. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.d.ts +1 -6
  227. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.d.ts.map +1 -1
  228. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.js +16 -332
  229. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.d.ts +1 -6
  230. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.d.ts.map +1 -1
  231. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.js +25 -358
  232. package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts +0 -5
  233. package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts.map +1 -1
  234. package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.js +201 -276
  235. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts +1 -0
  236. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts.map +1 -1
  237. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.js +167 -143
  238. package/src/shade/renderer/shader/graph/graph_create_buffer.d.ts +15 -0
  239. package/src/shade/renderer/shader/graph/graph_create_buffer.d.ts.map +1 -0
  240. package/src/shade/renderer/shader/graph/graph_create_buffer.js +20 -0
  241. package/src/shade/renderer/view/GPUViewContext.d.ts +3 -4
  242. package/src/shade/renderer/view/GPUViewContext.d.ts.map +1 -1
  243. package/src/shade/renderer/view/GPUViewContext.js +5 -5
  244. package/src/core/binary/meshopt/__meshopt_test_streams.d.ts +0 -24
  245. package/src/core/binary/meshopt/__meshopt_test_streams.d.ts.map +0 -1
  246. package/src/core/binary/meshopt/__meshopt_test_streams.js +0 -237
  247. package/src/core/geom/3d/atlas/atlas_test_fixtures.d.ts +0 -84
  248. package/src/core/geom/3d/atlas/atlas_test_fixtures.d.ts.map +0 -1
  249. package/src/core/geom/3d/atlas/atlas_test_fixtures.js +0 -266
  250. package/src/engine/asset/loaders/gltf_test_fixtures.d.ts +0 -97
  251. package/src/engine/asset/loaders/gltf_test_fixtures.d.ts.map +0 -1
  252. package/src/engine/asset/loaders/gltf_test_fixtures.js +0 -359
  253. package/src/shade/renderer/animation/skin_test_fixtures.d.ts +0 -86
  254. package/src/shade/renderer/animation/skin_test_fixtures.d.ts.map +0 -1
  255. package/src/shade/renderer/animation/skin_test_fixtures.js +0 -250
  256. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.d.ts +0 -16
  257. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.d.ts.map +0 -1
  258. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.js +0 -27
  259. package/src/shade/renderer/particles/particle_test_fixtures.d.ts +0 -151
  260. package/src/shade/renderer/particles/particle_test_fixtures.d.ts.map +0 -1
  261. package/src/shade/renderer/particles/particle_test_fixtures.js +0 -229
  262. package/src/shade/renderer/particles/shaders/chunk_particle_emitter_world_sphere.js +0 -23
  263. package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.js +0 -457
@@ -0,0 +1,318 @@
1
+ import { atomic_u32, f32, u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
+ import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
3
+ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
4
+ import { COLLECTION_U32_STRUCT_READ } from "../../gpu_primitive/COLLECTION_U32_STRUCT_READ.js";
5
+ import { ComputeShader } from "../../shader/ComputeShader.js";
6
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
7
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
8
+ import {
9
+ PARTICLE_RECORD_WORD_COUNT,
10
+ PARTICLE_WARMUP_LAUNCH_LANES,
11
+ PARTICLE_WARMUP_QUEUE_WORDS,
12
+ PARTICLE_WARMUP_WORKGROUP_SIZE,
13
+ } from "../ParticleConstants.js";
14
+ import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
15
+ import { PARTICLE_EMITTER_DESCRIPTOR, PARTICLE_EMITTER_STATE_DESCRIPTOR } from "../data/PARTICLE_DATABASE_SPEC.js";
16
+ import { chunk_particle_spawn_budget } from "../shaders/chunk_particle_spawn_budget.js";
17
+
18
+ /**
19
+ * The passes that are the warm-up's own. The rest of the loop is the main pipeline's, bound to a
20
+ * population of its own — see `./graph_particle_warmup.js` for the loop and for why it is separate.
21
+ *
22
+ * - {@link shader_particle_warmup_init} — hand the transient pool its free list, once per warm-up.
23
+ * - {@link shader_particle_warmup_reset} — roll the transient counters over, once per tick.
24
+ * - {@link shader_particle_warmup_tick} — one thread per queued emitter: the spawn decision for a
25
+ * tick, over a queue the host wrote rather than over the emitter table.
26
+ * - {@link shader_particle_warmup_migrate} — one thread per warmed particle: move it into the main
27
+ * pool, once the loop is done.
28
+ *
29
+ * Everything the warm-up integrates per emitter lives in the queue entry (its accumulator), not in
30
+ * the emitter's state row — with one exception, deliberately: the emitter's *age*. INIT and UPDATE
31
+ * read `EMITTER_AGE` off the state row through the same chunk whether the main emit pass or the
32
+ * warm-up's runs them, so the warm-up tick writes the age the emitter has reached into that row as it
33
+ * goes. When the loop ends the row says `prewarm`, and the next real tick adds its `dt` to that.
34
+ */
35
+
36
+ /**
37
+ * Word offsets within one entry of the warm-up queue the host writes:
38
+ * `[emitter row, pre-warm seconds, spawn accumulator, clock]`.
39
+ *
40
+ * The accumulator is the host's to seed and the GPU's from then on — a fraction in `[0, 1)` hashed
41
+ * from the row, so that two emitters queued together do not put their first whole particle on the
42
+ * same tick. The clock is the emitter's own tick rate, `1 ± PARTICLE_WARMUP_EMITTER_JITTER / 2`, for
43
+ * the same reason a beat further in.
44
+ *
45
+ * Raw words rather than a `WebGPUStruct`, like the spawn-command list: it is a short host-authored
46
+ * list read once a tick, and the floats are `bitcast` on the way in and out.
47
+ */
48
+ export const WARMUP_QUEUE = Object.freeze({
49
+ ROW: 0,
50
+ PREWARM: 1,
51
+ ACCUMULATOR: 2,
52
+ CLOCK: 3,
53
+ });
54
+
55
+ /** Workgroups the bounded per-particle passes launch. */
56
+ export const PARTICLE_WARMUP_WORKGROUP_COUNT = PARTICLE_WARMUP_LAUNCH_LANES / PARTICLE_WARMUP_WORKGROUP_SIZE;
57
+
58
+ const WG = PARTICLE_WARMUP_WORKGROUP_SIZE;
59
+
60
+ // --- init -------------------------------------------------------------------------------------
61
+
62
+ const init_resources = new ShaderResourceSetDescriptor();
63
+
64
+ init_resources.setImmediate("u_capacity", u32);
65
+
66
+ init_resources.createGroup()
67
+ .addStorageBuffer("dead", WebGPUArray.u32, true)
68
+ .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true);
69
+
70
+ /**
71
+ * One thread per slot of the transient pool: every slot onto the free list, and the counters to
72
+ * match. What the main system does once on the CPU when it allocates its pool, done on the GPU here
73
+ * because the pool is a graph transient and there is no CPU moment to write it in.
74
+ *
75
+ * @type {ComputeShader}
76
+ */
77
+ export const shader_particle_warmup_init = ComputeShader.from({
78
+ label: "Particle Warm-up Init",
79
+ resources: init_resources,
80
+ body: CodeChunk.from(/* language=wgsl */ `
81
+ @compute @workgroup_size(${WG}, 1, 1)
82
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
83
+ let i = gid.x;
84
+
85
+ if (i == 0u) {
86
+ atomicStore(&counters[${PARTICLE_COUNTER.DEAD}u], u_capacity);
87
+ atomicStore(&counters[${PARTICLE_COUNTER.ALIVE}u], 0u);
88
+ atomicStore(&counters[${PARTICLE_COUNTER.ALIVE_IN}u], 0u);
89
+ }
90
+
91
+ if (i >= u_capacity) { return; }
92
+
93
+ dead[i] = i;
94
+ }
95
+ `),
96
+ });
97
+
98
+ // --- reset ------------------------------------------------------------------------------------
99
+
100
+ const reset_resources = new ShaderResourceSetDescriptor();
101
+
102
+ reset_resources.createGroup()
103
+ .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true);
104
+
105
+ /**
106
+ * The top of a warm-up tick: last tick's alive list becomes this tick's advance input, the alive
107
+ * count starts over, and the tick's spawn budget is the free list as it stands.
108
+ *
109
+ * The main frame splits this between its reset pass and its build-indirect pass, because its
110
+ * simulate consumes the program-coherent list the bucketing built rather than the alive list
111
+ * itself. The warm-up's advance consumes the alive list directly (see `./chunk_particle_warmup_step.js`
112
+ * for why it can), so the snapshot is just the count.
113
+ *
114
+ * @type {ComputeShader}
115
+ */
116
+ export const shader_particle_warmup_reset = ComputeShader.from({
117
+ label: "Particle Warm-up Reset",
118
+ resources: reset_resources,
119
+ body: CodeChunk.from(/* language=wgsl */ `
120
+ @compute @workgroup_size(1, 1, 1)
121
+ fn main() {
122
+ atomicStore(&counters[${PARTICLE_COUNTER.ALIVE_IN}u], atomicLoad(&counters[${PARTICLE_COUNTER.ALIVE}u]));
123
+ atomicStore(&counters[${PARTICLE_COUNTER.ALIVE}u], 0u);
124
+ atomicStore(&counters[${PARTICLE_COUNTER.SPAWN_BUDGET}u], atomicLoad(&counters[${PARTICLE_COUNTER.DEAD}u]));
125
+ }
126
+ `),
127
+ });
128
+
129
+ // --- tick -------------------------------------------------------------------------------------
130
+
131
+ /**
132
+ * Per-dispatch, 20 bytes, read-only.
133
+ * @type {WebGPUStruct}
134
+ */
135
+ export const WARMUP_TICK_SETTINGS = WebGPUStruct.from({
136
+ /** seconds this tick advances the population by */
137
+ u_dt: f32,
138
+ /** seconds from the start of this tick to "now" — the end of the loop */
139
+ u_remaining: f32,
140
+ /** transient pool capacity — the accumulator's ceiling and the budget's wrap guard */
141
+ u_capacity: u32,
142
+ /** element capacity of the emitter table — the length of the counts list the scan consumes */
143
+ u_emitter_capacity: u32,
144
+ /** entries in the queue */
145
+ u_count: u32,
146
+ }, "ParticleWarmupTickSettings");
147
+
148
+ const EMITTER = PARTICLE_EMITTER_DESCRIPTOR;
149
+ const STATE = PARTICLE_EMITTER_STATE_DESCRIPTOR;
150
+
151
+ // Generated once and held: each call builds a fresh chunk declaring the same function.
152
+ const WRITE_AGE = STATE.wgsl_gen_write_field_code("age");
153
+
154
+ const tick_resources = new ShaderResourceSetDescriptor();
155
+
156
+ tick_resources.setImmediate("settings", WARMUP_TICK_SETTINGS);
157
+
158
+ tick_resources.createGroup()
159
+ .addStorageBuffer("queue", WebGPUArray.u32, true)
160
+ .addStorageBuffer("emitter_database", WebGPUArray.u32, true)
161
+ .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true)
162
+ .addStorageBuffer("spawn_counts", COLLECTION_U32_STRUCT_READ, true);
163
+
164
+ /**
165
+ * One thread per queued emitter: how many particles it spawns this tick.
166
+ *
167
+ * The main emitter tick's spawn decision — integrate the rate, take from the budget, write the
168
+ * count by row for the scan — over the host's queue instead of the emitter table, and without the
169
+ * parts that belong to a live frame: no generation test (the host holds the queue for exactly one
170
+ * frame), no culling (a warm-up is what makes an emitter measurable in the first place), no pending
171
+ * bursts (they are the frame's, not the past's).
172
+ *
173
+ * ## When an emitter takes part
174
+ *
175
+ * Once `u_remaining` is within its own pre-warm: the loop's clock counts down to now, and an emitter
176
+ * joins it when the time left is what it asked to have been running for. Two emitters queued with
177
+ * different durations therefore end the same loop having each run for its own — the shorter one
178
+ * simply sat out the start — rather than the shorter one being run for the longer's time and
179
+ * arriving with a population that is all dead of old age.
180
+ *
181
+ * ## The count list is the emitter table's
182
+ *
183
+ * The counts are written by emitter *row*, into a list as long as the table, exactly as the main
184
+ * tick writes them. That is what lets the main emit pass be reused unchanged: it finds a newborn's
185
+ * emitter by searching the scan of that list, and the row it finds is the row its record reads.
186
+ * Rows not in the queue count zero, which the cleared buffer already says.
187
+ *
188
+ * @type {ComputeShader}
189
+ */
190
+ export const shader_particle_warmup_tick = ComputeShader.from({
191
+ label: "Particle Warm-up Tick",
192
+ resources: tick_resources,
193
+ body: CodeChunk.from(/* language=wgsl */ `
194
+ const WARMUP_QUEUE_WORDS : u32 = ${PARTICLE_WARMUP_QUEUE_WORDS}u;
195
+ const WARMUP_Q_ROW : u32 = ${WARMUP_QUEUE.ROW}u;
196
+ const WARMUP_Q_PREWARM : u32 = ${WARMUP_QUEUE.PREWARM}u;
197
+ const WARMUP_Q_ACCUMULATOR : u32 = ${WARMUP_QUEUE.ACCUMULATOR}u;
198
+ const WARMUP_Q_CLOCK : u32 = ${WARMUP_QUEUE.CLOCK}u;
199
+
200
+ @compute @workgroup_size(${WG}, 1, 1)
201
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
202
+ let i = gid.x;
203
+
204
+ // The scan reads exactly this many counts, queued or not.
205
+ if (i == 0u) {
206
+ spawn_counts.count = settings.u_emitter_capacity;
207
+ }
208
+
209
+ if (i >= settings.u_count) { return; }
210
+
211
+ let base = i * WARMUP_QUEUE_WORDS;
212
+ let row = queue[base + WARMUP_Q_ROW];
213
+ let prewarm = bitcast<f32>(queue[base + WARMUP_Q_PREWARM]);
214
+ var accumulator = bitcast<f32>(queue[base + WARMUP_Q_ACCUMULATOR]);
215
+ let clock = bitcast<f32>(queue[base + WARMUP_Q_CLOCK]);
216
+
217
+ var count = 0u;
218
+
219
+ if (settings.u_remaining <= prewarm) {
220
+ let em = ${EMITTER.marshalling_method_read_rw}(&emitter_database, row);
221
+
222
+ // This emitter's own beat: the tick, at its own clock.
223
+ accumulator = min(accumulator + em.spawn_rate * settings.u_dt * clock, f32(settings.u_capacity));
224
+
225
+ let wanted = u32(floor(accumulator));
226
+
227
+ if (wanted > 0u) {
228
+ count = particle_take_spawn_budget(wanted, settings.u_capacity);
229
+ accumulator = accumulator - f32(count);
230
+ }
231
+
232
+ // How long the emitter has been running once this tick is done — what this tick's newborns
233
+ // and advances read as EMITTER_AGE, on the row the main passes read it from too.
234
+ ${STATE.marshalling_method_write_field("age")}(&emitter_database, row, prewarm - settings.u_remaining + settings.u_dt);
235
+ }
236
+
237
+ spawn_counts.elements[row] = count;
238
+ queue[base + WARMUP_Q_ACCUMULATOR] = bitcast<u32>(accumulator);
239
+ }
240
+ `, [
241
+ EMITTER.chunk_read_rw,
242
+ WRITE_AGE,
243
+ chunk_particle_spawn_budget,
244
+ ]),
245
+ });
246
+
247
+ // --- migrate ----------------------------------------------------------------------------------
248
+
249
+ const migrate_resources = new ShaderResourceSetDescriptor();
250
+
251
+ migrate_resources.setImmediate("u_capacity", u32);
252
+
253
+ migrate_resources.createGroup()
254
+ .addStorageBuffer("warm_pool", WebGPUArray.u32, false)
255
+ .addStorageBuffer("warm_alive", WebGPUArray.u32, false)
256
+ .addStorageBuffer("warm_counters", WebGPUArray.from(atomic_u32), true)
257
+ .addStorageBuffer("pool", WebGPUArray.u32, true)
258
+ .addStorageBuffer("alive_out", WebGPUArray.u32, true)
259
+ .addStorageBuffer("dead", WebGPUArray.u32, true)
260
+ .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true);
261
+
262
+ /**
263
+ * One thread per particle the loop left alive: a slot from the main pool, the record copied into
264
+ * it, and the slot onto the main alive list. The moment the warm-up's population becomes the
265
+ * scene's.
266
+ *
267
+ * The pop is the emit pass's, wrap guard and all, and it is the only thing this pass does to the
268
+ * main free list: it never pushes, so it is safe against nothing and needs no ordering beyond
269
+ * running after the main emit and simulate of the frame, which the graph gives it. A particle the
270
+ * main pool has no room for is dropped, as a spawn the pool has no room for is.
271
+ *
272
+ * The record is copied whole, header included. The header names the emitter's main-table row and
273
+ * generation — the warm-up's emit stamped it from the same record the main emit reads — so the
274
+ * copied particle is an ordinary one to every pass that meets it from here on.
275
+ *
276
+ * Bounded launch, grid stride over the transient alive count: the population is small and nothing
277
+ * should size a dispatch from the host to cover it.
278
+ *
279
+ * @type {ComputeShader}
280
+ */
281
+ export const shader_particle_warmup_migrate = ComputeShader.from({
282
+ label: "Particle Warm-up Migrate",
283
+ resources: migrate_resources,
284
+ body: CodeChunk.from(/* language=wgsl */ `
285
+ const COUNTER_ALIVE : u32 = ${PARTICLE_COUNTER.ALIVE}u;
286
+ const COUNTER_DEAD : u32 = ${PARTICLE_COUNTER.DEAD}u;
287
+ const WARMUP_LAUNCH_LANES : u32 = ${PARTICLE_WARMUP_LAUNCH_LANES}u;
288
+ const WARMUP_RECORD_WORDS : u32 = ${PARTICLE_RECORD_WORD_COUNT}u;
289
+
290
+ @compute @workgroup_size(${WG}, 1, 1)
291
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
292
+ let total = atomicLoad(&warm_counters[COUNTER_ALIVE]);
293
+
294
+ for (var i = gid.x; i < total; i = i + WARMUP_LAUNCH_LANES) {
295
+ let src = warm_alive[i];
296
+
297
+ // Pop a free slot off the main dead-list stack; drop the particle if the pool is exhausted.
298
+ // The guard catches WRAPPED values, not just 0 — see chunk_particle_emit_step for why.
299
+ let old_dead = atomicSub(&counters[COUNTER_DEAD], 1u);
300
+ if (old_dead == 0u || old_dead > u_capacity) {
301
+ atomicAdd(&counters[COUNTER_DEAD], 1u); // undo the over-pop
302
+ continue;
303
+ }
304
+ let dst = dead[old_dead - 1u];
305
+
306
+ let src_base = src * WARMUP_RECORD_WORDS;
307
+ let dst_base = dst * WARMUP_RECORD_WORDS;
308
+
309
+ for (var w = 0u; w < WARMUP_RECORD_WORDS; w = w + 1u) {
310
+ pool[dst_base + w] = warm_pool[src_base + w];
311
+ }
312
+
313
+ let a = atomicAdd(&counters[COUNTER_ALIVE], 1u);
314
+ alive_out[a] = dst;
315
+ }
316
+ }
317
+ `),
318
+ });
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The warm-up's advance pass over the fast register file: one warm-up tick of UPDATE over every
3
+ * particle the previous tick left alive, compacting survivors into the next alive list and the dead
4
+ * onto the transient free list.
5
+ *
6
+ * What the main simulate pass is to a frame, this is to a warm-up tick, and it is a shader of its
7
+ * own rather than that pass bound to other buffers for the reasons `./chunk_particle_warmup_step.js`
8
+ * gives: it reads the alive list directly, so it decodes per lane, and it jitters the tick per
9
+ * particle. Nothing about it is linked into the main passes.
10
+ *
11
+ * A bounded launch with a grid-stride loop over the transient alive count — the wide interpreter's
12
+ * shape — so no indirect-args pass is needed per tick and the loop's passes are all sized by
13
+ * constants. `alive_in` is the list the previous tick built (or the emit pass of this one appended
14
+ * to, on the pass before); `alive_out` is the other of the pair.
15
+ *
16
+ * @type {ComputeShader}
17
+ */
18
+ /**
19
+ * Per-dispatch, 12 bytes, read-only. The same three numbers the main simulate takes, as a struct of
20
+ * this pass's own rather than that pass's export: the two must be free to diverge.
21
+ * @type {WebGPUStruct}
22
+ */
23
+ export const WARMUP_ADVANCE_SETTINGS: WebGPUStruct;
24
+ /**
25
+ * The entry point both register backings share, as WGSL text: the wide variant prepends its
26
+ * register bind and is otherwise this.
27
+ * @type {string}
28
+ */
29
+ export const WARMUP_ADVANCE_BODY: string;
30
+ export const shader_particle_warmup_advance: ComputeShader;
31
+ export { PARTICLE_WARMUP_WORKGROUP_COUNT };
32
+ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
33
+ import { ComputeShader } from "../../shader/ComputeShader.js";
34
+ import { PARTICLE_WARMUP_WORKGROUP_COUNT } from "./shader_particle_warmup.js";
35
+ //# sourceMappingURL=shader_particle_warmup_advance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_particle_warmup_advance.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/warmup/shader_particle_warmup_advance.js"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;GAIG;AACH,sCAFU,YAAY,CAMc;AAgBpC;;;;GAIG;AACH,kCAFU,MAAM,CA6Bd;AAEF,2DAeG;;6BAvG0B,mCAAmC;8BAClC,+BAA+B;gDAQb,6BAA6B"}
@@ -0,0 +1,108 @@
1
+ import { atomic_u32, f32, u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
2
+ import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
3
+ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
4
+ import { ComputeShader } from "../../shader/ComputeShader.js";
5
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
6
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
7
+ import { PARTICLE_WARMUP_LAUNCH_LANES, PARTICLE_WARMUP_WORKGROUP_SIZE } from "../ParticleConstants.js";
8
+ import { PARTICLE_COUNTER } from "../data/PARTICLE_COUNTERS.js";
9
+ import { chunk_particle_curve_disabled } from "../shaders/chunk_particle_curve_disabled.js";
10
+ import { chunk_particle_vm_registers_fast } from "../vm/chunk_particle_vm_registers_fast.js";
11
+ import { chunk_particle_warmup_step } from "./chunk_particle_warmup_step.js";
12
+ import { PARTICLE_WARMUP_WORKGROUP_COUNT } from "./shader_particle_warmup.js";
13
+
14
+ /**
15
+ * The warm-up's advance pass over the fast register file: one warm-up tick of UPDATE over every
16
+ * particle the previous tick left alive, compacting survivors into the next alive list and the dead
17
+ * onto the transient free list.
18
+ *
19
+ * What the main simulate pass is to a frame, this is to a warm-up tick, and it is a shader of its
20
+ * own rather than that pass bound to other buffers for the reasons `./chunk_particle_warmup_step.js`
21
+ * gives: it reads the alive list directly, so it decodes per lane, and it jitters the tick per
22
+ * particle. Nothing about it is linked into the main passes.
23
+ *
24
+ * A bounded launch with a grid-stride loop over the transient alive count — the wide interpreter's
25
+ * shape — so no indirect-args pass is needed per tick and the loop's passes are all sized by
26
+ * constants. `alive_in` is the list the previous tick built (or the emit pass of this one appended
27
+ * to, on the pass before); `alive_out` is the other of the pair.
28
+ *
29
+ * @type {ComputeShader}
30
+ */
31
+
32
+ /**
33
+ * Per-dispatch, 12 bytes, read-only. The same three numbers the main simulate takes, as a struct of
34
+ * this pass's own rather than that pass's export: the two must be free to diverge.
35
+ * @type {WebGPUStruct}
36
+ */
37
+ export const WARMUP_ADVANCE_SETTINGS = WebGPUStruct.from({
38
+ u_dt: f32,
39
+ u_time: f32,
40
+ u_frame: u32,
41
+ }, "ParticleWarmupAdvanceSettings");
42
+
43
+ const resources = new ShaderResourceSetDescriptor();
44
+
45
+ resources.setImmediate("settings", WARMUP_ADVANCE_SETTINGS);
46
+
47
+ resources.createGroup()
48
+ .addStorageBuffer("scene_database", WebGPUArray.u32, false)
49
+ .addStorageBuffer("emitter_database", WebGPUArray.u32, false)
50
+ .addStorageBuffer("program", WebGPUArray.u32, false)
51
+ .addStorageBuffer("pool", WebGPUArray.u32, true)
52
+ .addStorageBuffer("alive_in", WebGPUArray.u32, false)
53
+ .addStorageBuffer("alive_out", WebGPUArray.u32, true)
54
+ .addStorageBuffer("dead", WebGPUArray.u32, true)
55
+ .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true);
56
+
57
+ /**
58
+ * The entry point both register backings share, as WGSL text: the wide variant prepends its
59
+ * register bind and is otherwise this.
60
+ * @type {string}
61
+ */
62
+ export const WARMUP_ADVANCE_BODY = /* language=wgsl */ `
63
+ const COUNTER_ALIVE : u32 = ${PARTICLE_COUNTER.ALIVE}u;
64
+ const COUNTER_DEAD : u32 = ${PARTICLE_COUNTER.DEAD}u;
65
+ const COUNTER_ALIVE_IN : u32 = ${PARTICLE_COUNTER.ALIVE_IN}u;
66
+ const WARMUP_LAUNCH_LANES : u32 = ${PARTICLE_WARMUP_LAUNCH_LANES}u;
67
+
68
+ fn particle_warmup_advance_all(lane : u32) {
69
+ let total = atomicLoad(&counters[COUNTER_ALIVE_IN]);
70
+
71
+ for (var i = lane; i < total; i = i + WARMUP_LAUNCH_LANES) {
72
+ let slot = alive_in[i];
73
+
74
+ let survived = particle_warmup_advance_one(
75
+ &scene_database, &emitter_database, &program, &pool,
76
+ slot,
77
+ settings.u_dt, settings.u_time, settings.u_frame,
78
+ );
79
+
80
+ if (survived) {
81
+ let a = atomicAdd(&counters[COUNTER_ALIVE], 1u);
82
+ alive_out[a] = slot;
83
+ } else {
84
+ let d = atomicAdd(&counters[COUNTER_DEAD], 1u);
85
+ dead[d] = slot;
86
+ }
87
+ }
88
+ }
89
+ `;
90
+
91
+ export const shader_particle_warmup_advance = ComputeShader.from({
92
+ label: "Particle Warm-up Advance",
93
+ resources,
94
+ body: CodeChunk.from(/* language=wgsl */ `
95
+ ${WARMUP_ADVANCE_BODY}
96
+
97
+ @compute @workgroup_size(${PARTICLE_WARMUP_WORKGROUP_SIZE}, 1, 1)
98
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
99
+ particle_warmup_advance_all(gid.x);
100
+ }
101
+ `, [
102
+ chunk_particle_warmup_step,
103
+ chunk_particle_vm_registers_fast,
104
+ chunk_particle_curve_disabled,
105
+ ]),
106
+ });
107
+
108
+ export { PARTICLE_WARMUP_WORKGROUP_COUNT };
@@ -0,0 +1,3 @@
1
+ export const shader_particle_warmup_advance_wide: ComputeShader;
2
+ import { ComputeShader } from "../../shader/ComputeShader.js";
3
+ //# sourceMappingURL=shader_particle_warmup_advance_wide.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_particle_warmup_advance_wide.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.js"],"names":[],"mappings":"AAkDA,gEAmBG;8BAlE2B,+BAA+B"}
@@ -0,0 +1,70 @@
1
+ import { assert } from "../../../../core/assert.js";
2
+ import { atomic_u32, f32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
3
+ import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
4
+ import { ComputeShader } from "../../shader/ComputeShader.js";
5
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
6
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
7
+ import {
8
+ PARTICLE_VM_WIDE_LAUNCH_LANES,
9
+ PARTICLE_WARMUP_LAUNCH_LANES,
10
+ PARTICLE_WARMUP_WORKGROUP_SIZE,
11
+ } from "../ParticleConstants.js";
12
+ import { chunk_particle_curve_disabled } from "../shaders/chunk_particle_curve_disabled.js";
13
+ import { chunk_particle_vm_registers_wide } from "../vm/chunk_particle_vm_registers_wide.js";
14
+ import { chunk_particle_warmup_step } from "./chunk_particle_warmup_step.js";
15
+ import { WARMUP_ADVANCE_BODY, WARMUP_ADVANCE_SETTINGS } from "./shader_particle_warmup_advance.js";
16
+
17
+ /**
18
+ * The warm-up's advance pass over the WIDE register file — for a system whose hungriest effect has
19
+ * put the interpreter on the storage-backed file. Same pass as
20
+ * {@link ./shader_particle_warmup_advance.js}, same entry point text, plus the register bind and the
21
+ * ninth binding, exactly as the main simulate's wide variant relates to its fast one.
22
+ *
23
+ * The register file is indexed by launch lane and reused across the grid-stride loop's iterations,
24
+ * which is sound for the reason `../vm/chunk_particle_vm_registers_wide.js` gives: a program writes
25
+ * a register before it reads it. It is the same buffer the main wide passes use, sized by
26
+ * {@link PARTICLE_VM_WIDE_LAUNCH_LANES}, which is why the warm-up's launch must be exactly that wide.
27
+ *
28
+ * @type {ComputeShader}
29
+ */
30
+
31
+ assert.equal(
32
+ PARTICLE_WARMUP_LAUNCH_LANES, PARTICLE_VM_WIDE_LAUNCH_LANES,
33
+ "the warm-up's launch must match the wide register file's lane count, which sizes the file",
34
+ );
35
+
36
+ const resources = new ShaderResourceSetDescriptor();
37
+
38
+ resources.setImmediate("settings", WARMUP_ADVANCE_SETTINGS);
39
+
40
+ resources.createGroup()
41
+ .addStorageBuffer("scene_database", WebGPUArray.u32, false)
42
+ .addStorageBuffer("emitter_database", WebGPUArray.u32, false)
43
+ .addStorageBuffer("program", WebGPUArray.u32, false)
44
+ .addStorageBuffer("pool", WebGPUArray.u32, true)
45
+ .addStorageBuffer("alive_in", WebGPUArray.u32, false)
46
+ .addStorageBuffer("alive_out", WebGPUArray.u32, true)
47
+ .addStorageBuffer("dead", WebGPUArray.u32, true)
48
+ .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true)
49
+ .addStorageBuffer("vm_registers", WebGPUArray.from(f32), true);
50
+
51
+ export const shader_particle_warmup_advance_wide = ComputeShader.from({
52
+ label: "Particle Warm-up Advance (wide registers)",
53
+ resources,
54
+ body: CodeChunk.from(/* language=wgsl */ `
55
+ ${WARMUP_ADVANCE_BODY}
56
+
57
+ @compute @workgroup_size(${PARTICLE_WARMUP_WORKGROUP_SIZE}, 1, 1)
58
+ fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
59
+ // This invocation's column of the register file. The launch is exactly
60
+ // PARTICLE_WARMUP_LAUNCH_LANES wide, so gid.x is in range by construction.
61
+ particle_vm_bind_registers(gid.x);
62
+
63
+ particle_warmup_advance_all(gid.x);
64
+ }
65
+ `, [
66
+ chunk_particle_warmup_step,
67
+ chunk_particle_vm_registers_wide,
68
+ chunk_particle_curve_disabled,
69
+ ]),
70
+ });
@@ -0,0 +1,62 @@
1
+ /**
2
+ * How a batch of pre-warms is paid off: in how many ticks, and how long each is.
3
+ *
4
+ * Shared by the GPU loop (`./graph_particle_warmup.js`) and the editor's CPU preview
5
+ * (`editor/particles/effect/ParticleReferenceSimulation.js`), so the two integrate the same debt in
6
+ * the same steps and an author sees in the preview what the scene will show.
7
+ *
8
+ * The tick count is bounded and the tick length stretches to cover the debt — not the other way
9
+ * round — because the count is what the frame pays for: every tick is a handful of dispatches. A
10
+ * two-hundred-millisecond warm-up at a ten-millisecond floor is twenty ticks of ten; a three-second
11
+ * one is {@link PARTICLE_WARMUP_MAX_TICKS} ticks of ninety-odd.
12
+ *
13
+ * @typedef {object} WarmupSchedule
14
+ * @property {number} ticks how many times the loop runs; zero for nothing owed
15
+ * @property {number} dt seconds each tick advances the population by
16
+ * @property {number} duration `ticks * dt` — the loop's whole span, never less than the longest
17
+ * pre-warm in the batch and less than one tick more
18
+ */
19
+ /**
20
+ * @param {number} max_prewarm the longest pre-warm in the batch, seconds
21
+ * @returns {WarmupSchedule}
22
+ */
23
+ export function warmup_schedule(max_prewarm: number): WarmupSchedule;
24
+ /**
25
+ * Seconds between the start of tick `tick` and "now" — the moment the loop ends and the population
26
+ * joins the scene. An emitter takes part in a tick once this is within its own pre-warm, so that
27
+ * whatever the longest pre-warm in the batch was, every emitter has run for exactly its own by the
28
+ * end.
29
+ *
30
+ * @param {WarmupSchedule} schedule
31
+ * @param {number} tick
32
+ * @returns {number}
33
+ */
34
+ export function warmup_remaining(schedule: WarmupSchedule, tick: number): number;
35
+ /**
36
+ * How a batch of pre-warms is paid off: in how many ticks, and how long each is.
37
+ *
38
+ * Shared by the GPU loop (`./graph_particle_warmup.js`) and the editor's CPU preview
39
+ * (`editor/particles/effect/ParticleReferenceSimulation.js`), so the two integrate the same debt in
40
+ * the same steps and an author sees in the preview what the scene will show.
41
+ *
42
+ * The tick count is bounded and the tick length stretches to cover the debt — not the other way
43
+ * round — because the count is what the frame pays for: every tick is a handful of dispatches. A
44
+ * two-hundred-millisecond warm-up at a ten-millisecond floor is twenty ticks of ten; a three-second
45
+ * one is {@link PARTICLE_WARMUP_MAX_TICKS } ticks of ninety-odd.
46
+ */
47
+ export type WarmupSchedule = {
48
+ /**
49
+ * how many times the loop runs; zero for nothing owed
50
+ */
51
+ ticks: number;
52
+ /**
53
+ * seconds each tick advances the population by
54
+ */
55
+ dt: number;
56
+ /**
57
+ * `ticks * dt` — the loop's whole span, never less than the longest
58
+ * pre-warm in the batch and less than one tick more
59
+ */
60
+ duration: number;
61
+ };
62
+ //# sourceMappingURL=warmup_schedule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warmup_schedule.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/warmup/warmup_schedule.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;GAGG;AACH,6CAHW,MAAM,GACJ,cAAc,CAgB1B;AAED;;;;;;;;;GASG;AACH,2CAJW,cAAc,QACd,MAAM,GACJ,MAAM,CAIlB;;;;;;;;;;;;;;;;;WAtCa,MAAM;;;;QACN,MAAM;;;;;cACN,MAAM"}
@@ -0,0 +1,55 @@
1
+ import { assert } from "../../../../core/assert.js";
2
+ import { PARTICLE_WARMUP_MAX_TICKS, PARTICLE_WARMUP_TICK_SECONDS } from "../ParticleConstants.js";
3
+
4
+ /**
5
+ * How a batch of pre-warms is paid off: in how many ticks, and how long each is.
6
+ *
7
+ * Shared by the GPU loop (`./graph_particle_warmup.js`) and the editor's CPU preview
8
+ * (`editor/particles/effect/ParticleReferenceSimulation.js`), so the two integrate the same debt in
9
+ * the same steps and an author sees in the preview what the scene will show.
10
+ *
11
+ * The tick count is bounded and the tick length stretches to cover the debt — not the other way
12
+ * round — because the count is what the frame pays for: every tick is a handful of dispatches. A
13
+ * two-hundred-millisecond warm-up at a ten-millisecond floor is twenty ticks of ten; a three-second
14
+ * one is {@link PARTICLE_WARMUP_MAX_TICKS} ticks of ninety-odd.
15
+ *
16
+ * @typedef {object} WarmupSchedule
17
+ * @property {number} ticks how many times the loop runs; zero for nothing owed
18
+ * @property {number} dt seconds each tick advances the population by
19
+ * @property {number} duration `ticks * dt` — the loop's whole span, never less than the longest
20
+ * pre-warm in the batch and less than one tick more
21
+ */
22
+
23
+ /**
24
+ * @param {number} max_prewarm the longest pre-warm in the batch, seconds
25
+ * @returns {WarmupSchedule}
26
+ */
27
+ export function warmup_schedule(max_prewarm) {
28
+ assert.isNumber(max_prewarm, "max_prewarm");
29
+ assert.greaterThanOrEqual(max_prewarm, 0, "max_prewarm");
30
+
31
+ if (max_prewarm <= 0) {
32
+ return { ticks: 0, dt: 0, duration: 0 };
33
+ }
34
+
35
+ const dt = Math.max(PARTICLE_WARMUP_TICK_SECONDS, max_prewarm / PARTICLE_WARMUP_MAX_TICKS);
36
+
37
+ // `max / (max / MAX)` is MAX up to rounding, and a rounding error's `ceil` is MAX + 1.
38
+ const ticks = Math.min(PARTICLE_WARMUP_MAX_TICKS, Math.ceil(max_prewarm / dt));
39
+
40
+ return { ticks, dt, duration: ticks * dt };
41
+ }
42
+
43
+ /**
44
+ * Seconds between the start of tick `tick` and "now" — the moment the loop ends and the population
45
+ * joins the scene. An emitter takes part in a tick once this is within its own pre-warm, so that
46
+ * whatever the longest pre-warm in the batch was, every emitter has run for exactly its own by the
47
+ * end.
48
+ *
49
+ * @param {WarmupSchedule} schedule
50
+ * @param {number} tick
51
+ * @returns {number}
52
+ */
53
+ export function warmup_remaining(schedule, tick) {
54
+ return schedule.duration - tick * schedule.dt;
55
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"PostProcess.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/postprocess/PostProcess.js"],"names":[],"mappings":"AAGA;IAYI;;;OAGG;IACH,uCAIC;IAnBD;;OAEG;IACH,MAFU,IAAI,CAEV;IAGJ;;OAEG;IACH,KAFU,GAAG,CAEV;IAYH;;;OAGG;IACH,oBAFW,MAAM,QAIhB;IAED,sBACC;CACJ;qBAnCoB,gBAAgB;oBACjB,cAAc"}
1
+ {"version":3,"file":"PostProcess.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/postprocess/PostProcess.js"],"names":[],"mappings":"AAGA;IAYI;;;OAGG;IACH,uCAIC;IAnBD;;OAEG;IACH,MAFU,IAAI,CAEV;IAGJ;;OAEG;IACH,KAFU,GAAG,CAEV;IAYH;;;OAGG;IACH,oBAFW,MAAM,QAIhB;IAED,sBAEC;CACJ;qBApCoB,gBAAgB;oBACjB,cAAc"}