@woosh/meep-engine 3.17.1 → 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 (265) 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/engine/sound/simulation/core/OcclusionSolver.d.ts +0 -29
  254. package/src/engine/sound/simulation/core/OcclusionSolver.d.ts.map +0 -1
  255. package/src/shade/renderer/animation/skin_test_fixtures.d.ts +0 -86
  256. package/src/shade/renderer/animation/skin_test_fixtures.d.ts.map +0 -1
  257. package/src/shade/renderer/animation/skin_test_fixtures.js +0 -250
  258. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.d.ts +0 -16
  259. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.d.ts.map +0 -1
  260. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.js +0 -27
  261. package/src/shade/renderer/particles/particle_test_fixtures.d.ts +0 -151
  262. package/src/shade/renderer/particles/particle_test_fixtures.d.ts.map +0 -1
  263. package/src/shade/renderer/particles/particle_test_fixtures.js +0 -229
  264. package/src/shade/renderer/particles/shaders/chunk_particle_emitter_world_sphere.js +0 -23
  265. package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.js +0 -457
@@ -1,216 +1,213 @@
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 { CAMERA_UNIFORM_STRUCT } from "../../camera/CAMERA_UNIFORM_STRUCT.js";
5
- import { COLLECTION_U32_STRUCT_READ } from "../../gpu_primitive/COLLECTION_U32_STRUCT_READ.js";
6
- import { chunk_scene_database_access } from "../../scene/chunk_scene_database_access.js";
7
- import {
8
- chunk_sphere_intersects_frustum
9
- } from "../../shader/chunk/geometry/sphere/chunk_sphere_intersects_frustum.js";
10
- import { ComputeShader } from "../../shader/ComputeShader.js";
11
- import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
12
- import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
13
- import { PARTICLE_EMITTER_TICK_WORKGROUP_SIZE } 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 { EMITTER_FLAG } from "../data/PARTICLE_EMITTER_STRUCT.js";
17
- import { chunk_particle_emitter_world_sphere } from "./chunk_particle_emitter_world_sphere.js";
18
-
19
- /**
20
- * The emitter tick: one thread per emitter table row, deciding how many particles each emitter
21
- * spawns this frame. This is the pass that took spawning off the CPU — the host no longer walks the
22
- * emitters, and no longer knows or cares how many there are.
23
- *
24
- * Per live row it:
25
- *
26
- * 1. picks up the row's GPU-owned state (the `emitter_state` table, see
27
- * {@link ../data/PARTICLE_EMITTER_STATE.js}) — or starts it over, when the state's generation is
28
- * not the record's, which is how both a brand-new row and a reused one are recognised without
29
- * the CPU clearing anything;
30
- * 2. takes whatever the spawn-command pass queued into `pending` (the CPU's bursts, and in time
31
- * whatever a VM opcode asks for) into the accumulator;
32
- * 3. if the emitter opts into culling, tests its bounds sphere — in world space, through its scene
33
- * node's `global` — against the camera frustum; a culled emitter sleeps, accruing time it pays
34
- * back as a bounded burst when it is next seen;
35
- * 4. integrates `spawn_rate * dt`, and turns the whole part of the accumulator into this frame's
36
- * count — clamped by the frame's spawn budget, which the reset pass seeded from the dead count,
37
- * so an emitter is only ever debited for particles the pool can hold;
38
- * 5. writes that count to `spawn_counts.elements[row]`.
39
- *
40
- * `spawn_counts` is the input of a prefix scan, and the scan's inclusive sums are what the emit
41
- * pass expands: one thread per particle, each locating its emitter by binary search over the sums.
42
- * That is the same shape the rasteriser uses to expand meshes into meshlets, and it is what makes
43
- * the per-emitter count unbounded — no thread here loops over its particles.
44
- *
45
- * The rows are walked with the emitter table's page iterator, one page group per workgroup, so an
46
- * unallocated page costs one word read and a freed row costs one bit test. The state rows live in
47
- * the same database buffer, bound once and read-write, and are read and written whole: each row is
48
- * one thread's, so nothing here needs an atomic. Rows the walk skips leave their count at zero,
49
- * which is why the counts buffer is cleared before this runs. The scan's `count` header is written
50
- * by the first thread, from the table's element capacity, which is the only number the host
51
- * supplies.
52
- *
53
- * @type {ComputeShader}
54
- */
55
-
56
- const GROUP_SIZE = PARTICLE_EMITTER_TICK_WORKGROUP_SIZE;
57
-
58
- // The database is bound read-write (the state rows are written), so the iterator and the readers
59
- // are the `_rw` variants: WGSL does not coerce access modes at a call site.
60
- const PG = PARTICLE_EMITTER_DESCRIPTOR.page_iterator_symbol_prefix(GROUP_SIZE, true);
61
- const STATE = PARTICLE_EMITTER_STATE_DESCRIPTOR;
62
-
63
- /**
64
- * Per-dispatch, 16 bytes, read-only.
65
- *
66
- * @type {WebGPUStruct}
67
- */
68
- const TICK_SETTINGS = WebGPUStruct.from({
69
- /** seconds */
70
- u_dt: f32,
71
- /** cap on how much missed time a wake-up burst covers, seconds */
72
- u_max_catchup: f32,
73
- /** pool capacity — the ceiling on the accumulator, and the wrap guard for the budget counter */
74
- u_capacity: u32,
75
- /** element capacity of the emitter table — the length of the counts list the scan consumes */
76
- u_emitter_capacity: u32,
77
- }, 'ParticleEmitterTickSettings');
78
-
79
- const resources = new ShaderResourceSetDescriptor();
80
-
81
- resources.setImmediate('settings', TICK_SETTINGS);
82
-
83
- resources.createGroup()
84
- .addUniform("camera", CAMERA_UNIFORM_STRUCT)
85
- .addStorageBuffer("scene_database", WebGPUArray.u32, false)
86
- .addStorageBuffer("emitter_database", WebGPUArray.u32, true)
87
- .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true)
88
- .addStorageBuffer("spawn_counts", COLLECTION_U32_STRUCT_READ, true);
89
-
90
- const body = CodeChunk.from(/* language=wgsl */ `
91
- const COUNTER_SPAWN_BUDGET : u32 = ${PARTICLE_COUNTER.SPAWN_BUDGET}u;
92
- const EMITTER_FLAG_CULL : u32 = ${EMITTER_FLAG.CULL}u;
93
-
94
- // Take up to \`wanted\` from the frame's spawn budget; returns what was actually granted.
95
- //
96
- // Many rows race this counter. A thread that drives it below zero sees an old value smaller than
97
- // its request and keeps only that much; a thread that reads while another's over-subtraction is
98
- // still un-undone sees a wrapped (huge) value and keeps nothing. Each adds back exactly what it did
99
- // not keep, so the counter converges to zero rather than to garbage — the same shape as the dead
100
- // list pop in the emit pass.
101
- fn particle_take_spawn_budget(wanted : u32, capacity : u32) -> u32 {
102
- let old = atomicSub(&counters[COUNTER_SPAWN_BUDGET], wanted);
103
-
104
- var granted = wanted;
105
- if (old > capacity) {
106
- granted = 0u;
107
- } else if (old < wanted) {
108
- granted = old;
109
- }
110
-
111
- if (granted != wanted) {
112
- atomicAdd(&counters[COUNTER_SPAWN_BUDGET], wanted - granted);
113
- }
114
-
115
- return granted;
116
- }
117
-
118
- @compute @workgroup_size(${GROUP_SIZE}, 1, 1)
119
- fn main(
120
- @builtin(workgroup_id) wg_id : vec3<u32>,
121
- @builtin(local_invocation_index) local_id : u32,
122
- ) {
123
- // The scan reads exactly this many counts. Written before the page test so it lands even when
124
- // page 0 is unallocated — an empty table still has to scan to a total of zero.
125
- if (wg_id.x == 0u && local_id == 0u) {
126
- spawn_counts.count = settings.u_emitter_capacity;
127
- }
128
-
129
- // page_address is uniform across the workgroup, so this branch is uniform.
130
- if (!${PG}_setup(&emitter_database, wg_id.x, local_id)) {
131
- return;
132
- }
133
-
134
- let slot_in_page = ${PG}_slot_in_page(local_id);
135
-
136
- if (slot_in_page >= ${PG}_ELEMENTS_PER_PAGE || !${PG}_is_occupied(slot_in_page)) {
137
- return;
138
- }
139
-
140
- let em = ${PG}_read(&emitter_database, slot_in_page);
141
- let row = ${PG}_slot_to_index(slot_in_page);
142
-
143
- var state = ${STATE.marshalling_method_read_rw}(&emitter_database, row);
144
-
145
- // Whatever the spawn-command pass queued since last tick. Taken before the generation test so a
146
- // burst issued on the frame a row was (re)assigned is not lost with the stale state.
147
- let pending = state.pending;
148
- state.pending = 0u;
149
-
150
- if (state.generation != em.generation) {
151
- // A row this state has not seen: new emitter, or a reused row. Start from nothing.
152
- state.generation = em.generation;
153
- state.accumulator = 0.0;
154
- state.age = 0.0;
155
- state.sleep = 0.0;
156
- }
157
-
158
- var accumulator = state.accumulator + f32(pending);
159
- var sleep = state.sleep;
160
-
161
- state.age = state.age + settings.u_dt;
162
-
163
- var visible = true;
164
-
165
- if ((em.flags & EMITTER_FLAG_CULL) != 0u) {
166
- let node = scene_read_node(&scene_database, em.node);
167
- visible = sphere_intersects_frustum(particle_emitter_world_sphere(em, node.global), camera.frustum);
168
- }
169
-
170
- var count = 0u;
171
-
172
- if (visible) {
173
- // Waking up: a bounded catch-up for the time spent culled, so a long occlusion cannot
174
- // spike the pool on the frame the emitter comes back into view.
175
- if (sleep > 0.0) {
176
- accumulator = accumulator + em.spawn_rate * min(sleep, settings.u_max_catchup);
177
- sleep = 0.0;
178
- }
179
-
180
- accumulator = accumulator + em.spawn_rate * settings.u_dt;
181
-
182
- // A permanently over-subscribed emitter cannot grow its debt without limit.
183
- accumulator = min(accumulator, f32(settings.u_capacity));
184
-
185
- let wanted = u32(floor(accumulator));
186
-
187
- if (wanted > 0u) {
188
- count = particle_take_spawn_budget(wanted, settings.u_capacity);
189
- accumulator = accumulator - f32(count);
190
- }
191
- } else {
192
- sleep = sleep + settings.u_dt;
193
- }
194
-
195
- spawn_counts.elements[row] = count;
196
-
197
- state.accumulator = accumulator;
198
- state.sleep = sleep;
199
- ${STATE.marshalling_method_write}(&emitter_database, row, state);
200
- }
201
- `, [
202
- PARTICLE_EMITTER_DESCRIPTOR.chunk_iterate(GROUP_SIZE, true),
203
- STATE.chunk_read_rw,
204
- STATE.chunk_write,
205
- chunk_scene_database_access,
206
- chunk_sphere_intersects_frustum,
207
- chunk_particle_emitter_world_sphere,
208
- ]);
209
-
210
- export const shader_particle_emitter_tick = ComputeShader.from({
211
- label: "Particle Emitter Tick",
212
- resources,
213
- body,
214
- });
215
-
216
- export { PARTICLE_EMITTER_TICK_WORKGROUP_SIZE };
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 { CAMERA_UNIFORM_STRUCT } from "../../camera/CAMERA_UNIFORM_STRUCT.js";
5
+ import { COLLECTION_U32_STRUCT_READ } from "../../gpu_primitive/COLLECTION_U32_STRUCT_READ.js";
6
+ import { AABB3_STRUCT } from "../../shader/chunk/geometry/aabb3/AABB3_STRUCT.js";
7
+ import {
8
+ chunk_aabb3_intersects_frustum
9
+ } from "../../shader/chunk/geometry/aabb3/chunk_aabb3_intersects_frustum.js";
10
+ import { ComputeShader } from "../../shader/ComputeShader.js";
11
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
12
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
13
+ import { PARTICLE_EMITTER_TICK_WORKGROUP_SIZE } from "../ParticleConstants.js";
14
+ import { PARTICLE_EMITTER_DESCRIPTOR, PARTICLE_EMITTER_STATE_DESCRIPTOR } from "../data/PARTICLE_DATABASE_SPEC.js";
15
+ import { EMITTER_FLAG } from "../data/PARTICLE_EMITTER_STRUCT.js";
16
+ import { chunk_particle_spawn_budget } from "./chunk_particle_spawn_budget.js";
17
+ import { chunk_particle_bounds_unknown } from "../bounds/chunk_particle_bounds_unknown.js";
18
+
19
+ /**
20
+ * The emitter tick: one thread per emitter table row, deciding how many particles each emitter
21
+ * spawns this frame. This is the pass that took spawning off the CPU — the host no longer walks the
22
+ * emitters, and no longer knows or cares how many there are.
23
+ *
24
+ * Per live row it:
25
+ *
26
+ * 1. picks up the row's GPU-owned state (the `emitter_state` table, see
27
+ * {@link ../data/PARTICLE_EMITTER_STATE.js}) — or starts it over, when the state's generation is
28
+ * not the record's, which is how both a brand-new row and a reused one are recognised without
29
+ * the CPU clearing anything;
30
+ * 2. takes whatever the spawn-command pass queued into `pending` (the CPU's bursts, and in time
31
+ * whatever a VM opcode asks for) into the accumulator;
32
+ * 3. if the emitter opts into culling, tests the bounding box on its state row against the camera
33
+ * frustum; a culled emitter sleeps, accruing time it pays back as a bounded burst when it is
34
+ * next seen;
35
+ * 4. integrates `spawn_rate * dt`, and turns the whole part of the accumulator into this frame's
36
+ * count — clamped by the frame's spawn budget, which the reset pass seeded from the dead count,
37
+ * so an emitter is only ever debited for particles the pool can hold;
38
+ * 5. writes that count to `spawn_counts.elements[row]`.
39
+ *
40
+ * `spawn_counts` is the input of a prefix scan, and the scan's inclusive sums are what the emit
41
+ * pass expands: one thread per particle, each locating its emitter by binary search over the sums.
42
+ * That is the same shape the rasteriser uses to expand meshes into meshlets, and it is what makes
43
+ * the per-emitter count unbounded — no thread here loops over its particles.
44
+ *
45
+ * The rows are walked with the emitter table's page iterator, one page group per workgroup, so an
46
+ * unallocated page costs one word read and a freed row costs one bit test. The state rows live in
47
+ * the same database buffer, bound once and read-write, and are read and written whole: each row is
48
+ * one thread's, so nothing here needs an atomic. Rows the walk skips leave their count at zero,
49
+ * which is why the counts buffer is cleared before this runs. The scan's `count` header is written
50
+ * by the first thread, from the table's element capacity, which is the only number the host
51
+ * supplies.
52
+ *
53
+ * ## What it does not do
54
+ *
55
+ * It does not measure the box it culls with. An emitter has no bounds an author could declare, so
56
+ * they are measured from the live particles by a pass of their own at the end of the frame
57
+ * (`../bounds/`), which publishes into the same state row this reads. All that reaches here is the
58
+ * finished box and one frustum test — the emitter table is walked twice a frame rather than three
59
+ * times, and this pass stays about spawning.
60
+ *
61
+ * The box is therefore one frame old: it is over the particles that were alive when the last frame
62
+ * ended. That is the right staleness for what it decides. A wrongly culled emitter spawns nothing
63
+ * for a frame and is paid back by the wake-up catch-up; a wrongly woken one spawns particles it
64
+ * would have had a frame later anyway.
65
+ *
66
+ * A new row, and any row without measured live particles, is exempt from culling. Unknown bounds
67
+ * are an infinite box, recognized before the frustum math: even a sub-frame spawn rate must be able
68
+ * to accumulate its first particle when the emitter's origin is offscreen. Prewarm remains optional.
69
+ *
70
+ * @type {ComputeShader}
71
+ */
72
+
73
+ const GROUP_SIZE = PARTICLE_EMITTER_TICK_WORKGROUP_SIZE;
74
+
75
+ // The database is bound read-write (the state rows are written), so the iterator and the readers
76
+ // are the `_rw` variants: WGSL does not coerce access modes at a call site.
77
+ const PG = PARTICLE_EMITTER_DESCRIPTOR.page_iterator_symbol_prefix(GROUP_SIZE, true);
78
+ const STATE = PARTICLE_EMITTER_STATE_DESCRIPTOR;
79
+
80
+ /**
81
+ * Per-dispatch, 16 bytes, read-only.
82
+ *
83
+ * @type {WebGPUStruct}
84
+ */
85
+ const TICK_SETTINGS = WebGPUStruct.from({
86
+ /** seconds */
87
+ u_dt: f32,
88
+ /** cap on how much missed time a wake-up burst covers, seconds */
89
+ u_max_catchup: f32,
90
+ /** pool capacity — the ceiling on the accumulator, and the wrap guard for the budget counter */
91
+ u_capacity: u32,
92
+ /** element capacity of the emitter table — the length of the counts list the scan consumes */
93
+ u_emitter_capacity: u32,
94
+ }, 'ParticleEmitterTickSettings');
95
+
96
+ const resources = new ShaderResourceSetDescriptor();
97
+
98
+ resources.setImmediate('settings', TICK_SETTINGS);
99
+
100
+ resources.createGroup()
101
+ .addUniform("camera", CAMERA_UNIFORM_STRUCT)
102
+ .addStorageBuffer("emitter_database", WebGPUArray.u32, true)
103
+ .addStorageBuffer("counters", WebGPUArray.from(atomic_u32), true)
104
+ .addStorageBuffer("spawn_counts", COLLECTION_U32_STRUCT_READ, true);
105
+
106
+ const body = CodeChunk.from(/* language=wgsl */ `
107
+ const EMITTER_FLAG_CULL : u32 = ${EMITTER_FLAG.CULL}u;
108
+
109
+ @compute @workgroup_size(${GROUP_SIZE}, 1, 1)
110
+ fn main(
111
+ @builtin(workgroup_id) wg_id : vec3<u32>,
112
+ @builtin(local_invocation_index) local_id : u32,
113
+ ) {
114
+ // The scan reads exactly this many counts. Written before the page test so it lands even when
115
+ // page 0 is unallocated — an empty table still has to scan to a total of zero.
116
+ if (wg_id.x == 0u && local_id == 0u) {
117
+ spawn_counts.count = settings.u_emitter_capacity;
118
+ }
119
+
120
+ // page_address is uniform across the workgroup, so this branch is uniform.
121
+ if (!${PG}_setup(&emitter_database, wg_id.x, local_id)) {
122
+ return;
123
+ }
124
+
125
+ let slot_in_page = ${PG}_slot_in_page(local_id);
126
+
127
+ if (slot_in_page >= ${PG}_ELEMENTS_PER_PAGE || !${PG}_is_occupied(slot_in_page)) {
128
+ return;
129
+ }
130
+
131
+ let em = ${PG}_read(&emitter_database, slot_in_page);
132
+ let row = ${PG}_slot_to_index(slot_in_page);
133
+
134
+ var state = ${STATE.marshalling_method_read_rw}(&emitter_database, row);
135
+
136
+ // Whatever the spawn-command pass queued since last tick. Taken before the generation test so a
137
+ // burst issued on the frame a row was (re)assigned is not lost with the stale state.
138
+ let pending = state.pending;
139
+ state.pending = 0u;
140
+
141
+ // A row this state has not seen: new emitter, or a reused row. Start from nothing.
142
+ let restarted = state.generation != em.generation;
143
+
144
+ if (restarted) {
145
+ state.generation = em.generation;
146
+ state.accumulator = 0.0;
147
+ state.age = 0.0;
148
+ state.sleep = 0.0;
149
+ }
150
+
151
+ var accumulator = state.accumulator + f32(pending);
152
+ var sleep = state.sleep;
153
+
154
+ state.age = state.age + settings.u_dt;
155
+
156
+ var visible = true;
157
+
158
+ // \`restarted\` is what keeps a row's first tick out of this: nothing has measured it yet, and
159
+ // the box the CPU staged is not a statement about where the emitter is.
160
+ if (!restarted && !particle_bounds_unknown(state.bounds_min) && (em.flags & EMITTER_FLAG_CULL) != 0u) {
161
+ let box = ${AABB3_STRUCT.make({ min: "state.bounds_min", max: "state.bounds_max" })};
162
+
163
+ visible = aabb3_intersects_frustum(box, camera.frustum);
164
+ }
165
+
166
+ var count = 0u;
167
+
168
+ if (visible) {
169
+ // Waking up: a bounded catch-up for the time spent culled, so a long occlusion cannot
170
+ // spike the pool on the frame the emitter comes back into view.
171
+ if (sleep > 0.0) {
172
+ accumulator = accumulator + em.spawn_rate * min(sleep, settings.u_max_catchup);
173
+ sleep = 0.0;
174
+ }
175
+
176
+ accumulator = accumulator + em.spawn_rate * settings.u_dt;
177
+
178
+ // A permanently over-subscribed emitter cannot grow its debt without limit.
179
+ accumulator = min(accumulator, f32(settings.u_capacity));
180
+
181
+ let wanted = u32(floor(accumulator));
182
+
183
+ if (wanted > 0u) {
184
+ count = particle_take_spawn_budget(wanted, settings.u_capacity);
185
+ accumulator = accumulator - f32(count);
186
+ }
187
+ } else {
188
+ sleep = sleep + settings.u_dt;
189
+ }
190
+
191
+ spawn_counts.elements[row] = count;
192
+
193
+ state.accumulator = accumulator;
194
+ state.sleep = sleep;
195
+ ${STATE.marshalling_method_write}(&emitter_database, row, state);
196
+ }
197
+ `, [
198
+ PARTICLE_EMITTER_DESCRIPTOR.chunk_iterate(GROUP_SIZE, true),
199
+ STATE.chunk_read_rw,
200
+ STATE.chunk_write,
201
+ chunk_particle_spawn_budget,
202
+ chunk_particle_bounds_unknown,
203
+ chunk_aabb3_intersects_frustum,
204
+ AABB3_STRUCT.declaration_chunk,
205
+ ]);
206
+
207
+ export const shader_particle_emitter_tick = ComputeShader.from({
208
+ label: "Particle Emitter Tick",
209
+ resources,
210
+ body,
211
+ });
212
+
213
+ export { PARTICLE_EMITTER_TICK_WORKGROUP_SIZE };
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Return to the free list the slots the emit pass's pre-warm killed.
3
+ *
4
+ * A newborn of a pre-warming emitter runs its UPDATE program forward before it is shown
5
+ * ({@link ./chunk_particle_emit_step.js}), and one whose life runs out during that never belongs on
6
+ * the alive list. Its slot has to go back to the free list, and this pass is where that happens.
7
+ *
8
+ * ## Why it is a pass of its own
9
+ *
10
+ * Because emit is the one pass that POPS the free list, and a push racing a pop on an array stack
11
+ * hands one slot to two particles.
12
+ *
13
+ * The pop is `old = atomicSub(DEAD, 1)` followed by a read of `dead[old - 1]`; a push would be
14
+ * `d = atomicAdd(DEAD, 1)` followed by a write to `dead[d]`. Order one thread's `atomicSub` before
15
+ * another's `atomicAdd` and the two name the same index, with nothing between the atomic and the
16
+ * plain access to order them. If the write lands first, the popper takes the pushed slot AND leaves
17
+ * it on the stack under a count that now includes it — so the next popper takes it again, and two
18
+ * live particles share one record. That is precisely the failure the build-indirect pass warns about
19
+ * for a different reason, and it is why the emit pass writes to `dead` nowhere: even its
20
+ * pool-exhaustion path only ever puts the counter back.
21
+ *
22
+ * Between two dispatches there is no such race. This pass only pushes; nothing in it pops.
23
+ *
24
+ * ## Where the slots are between the two
25
+ *
26
+ * At the far end of `alive_out`, growing down from `capacity`, counted by
27
+ * {@link PARTICLE_COUNTER.STILLBORN}. A region of a buffer emit already binds, rather than a list of
28
+ * its own: emit binds exactly the eight storage buffers a compute stage gets by default, and a ninth
29
+ * for a list that is empty on all but a handful of frames is not what the ninth is for.
30
+ *
31
+ * The park cannot collide with the alive list growing up from zero. Every entry in either is a
32
+ * distinct pool slot and a parked one is by definition not alive, so the two lengths sum to at most
33
+ * the `capacity` entries between them.
34
+ *
35
+ * ## Sizing
36
+ *
37
+ * A bounded launch with a grid-stride loop, the shape the wide interpreter uses and for the same
38
+ * reason: the length it walks is a GPU-side count. Nothing about it is sized from the host, and the
39
+ * dispatch costs one atomic load and an exit on the frames — nearly all of them — where nothing was
40
+ * parked.
41
+ *
42
+ * @type {ComputeShader}
43
+ */
44
+ /** Workgroups this pass dispatches. Constant: the launch does not depend on how many slots were parked. */
45
+ export const PARTICLE_RECLAIM_WORKGROUP_COUNT: number;
46
+ export const shader_particle_reclaim: ComputeShader;
47
+ export { PARTICLE_RECLAIM_WORKGROUP_SIZE };
48
+ import { ComputeShader } from "../../shader/ComputeShader.js";
49
+ import { PARTICLE_RECLAIM_WORKGROUP_SIZE } from "../ParticleConstants.js";
50
+ //# sourceMappingURL=shader_particle_reclaim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_particle_reclaim.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_reclaim.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,2GAA2G;AAC3G,sDAAyG;AAWzG,oDAqBG;;8BAnF2B,+BAA+B;gDAGW,yBAAyB"}
@@ -72,7 +72,7 @@ fn fs_main(in : ParticleVertexOut) -> @location(0) vec4<f32> {
72
72
  let A = camera.device_depth_to_view_space.y;
73
73
  let B = camera.device_depth_to_view_space.x;
74
74
  let scene_vd = select(A / (scene_dev + B), 1e9, scene_dev <= 0.0);
75
- color.a = color.a * particle_soft_fade(scene_vd, in.view_depth, PARTICLE_SOFT_FADE_RANGE);
75
+ color = particle_fade_color(color, in.blend, particle_soft_fade(scene_vd, in.view_depth, PARTICLE_SOFT_FADE_RANGE));
76
76
  }
77
77
 
78
78
  if ((in.flags & PARTICLE_FLAG_LIGHTING) != 0u) {
@@ -0,0 +1,36 @@
1
+ /**
2
+ * What a warm-up tick does to one particle: run its emitter's UPDATE program over it, by a tick
3
+ * jittered for it alone, and say whether it lived.
4
+ *
5
+ * Shared by `./shader_particle_warmup_advance.js` and `./shader_particle_warmup_advance_wide.js`
6
+ * the way the main simulate's step is shared by its two register backings.
7
+ *
8
+ * ## Why this is not `particle_simulate_one`
9
+ *
10
+ * It is the same shape — header, record, node, context, program, verdict — and it differs in two
11
+ * things that are each the whole point of a separate pipeline.
12
+ *
13
+ * It decodes the program section **per lane**. The main step reads the section parameters from the
14
+ * wave's first lane, and is correct only because the bucketing passes regrouped the list so every
15
+ * wave holds one program. The warm-up feeds its advance the raw alive list — spawned by emitters that
16
+ * may run different programs, appended in whatever order the atomics landed — and would need the
17
+ * bucketing's six passes per tick to earn the broadcast. Per-lane decode costs the warm-up some of
18
+ * its own occupancy and nothing else, and the warm-up's occupancy is its own business: nothing here
19
+ * is linked into the main passes, and their compiled code is unchanged by this file existing.
20
+ *
21
+ * It **jitters the tick per particle**. Every particle born in one tick would otherwise reach the
22
+ * end of the loop with exactly that tick's age, and a warm-up of N ticks would arrive as N cohorts.
23
+ * A program does not care what `DELTA_TIME` it is handed, so each particle is advanced by
24
+ * `dt * (1 + PARTICLE_WARMUP_DT_JITTER * (u - 0.5))` for a `u` hashed from its slot and the tick —
25
+ * a hash and not a draw from `random()`, so the program's own random stream is exactly what it would
26
+ * have been.
27
+ *
28
+ * There is no padding sentinel to recognise: the list this reads is the alive list, which holds real
29
+ * slots only. The generation test is kept — the host holds the queue for one frame and an emitter
30
+ * cannot leave mid-loop, but the header carries the generation and honouring it is one compare.
31
+ *
32
+ * @type {CodeChunk}
33
+ */
34
+ export const chunk_particle_warmup_step: CodeChunk;
35
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
36
+ //# sourceMappingURL=chunk_particle_warmup_step.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_particle_warmup_step.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/warmup/chunk_particle_warmup_step.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,yCAFU,SAAS,CA0DhB;0BArGuB,oCAAoC"}