@woosh/meep-engine 3.41.0 → 3.43.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 (384) hide show
  1. package/build/bundle-worker-image-decoder.js +1 -1
  2. package/build/bundle-worker-terrain.js +1 -1
  3. package/editor/selection/editor_pick.d.ts.map +1 -1
  4. package/editor/selection/editor_pick.js +2 -1
  5. package/editor/tools/TransformToolV2.d.ts.map +1 -1
  6. package/editor/tools/TransformToolV2.js +7 -1
  7. package/editor/tools/engine/ToolEngine.d.ts.map +1 -1
  8. package/editor/tools/engine/ToolEngine.js +10 -0
  9. package/editor/tools/v2/TransformControls.d.ts.map +1 -1
  10. package/editor/tools/v2/TransformControls.js +7 -20
  11. package/editor/tools/v2/handle/gizmo_drag_plane.d.ts.map +1 -1
  12. package/editor/tools/v2/handle/gizmo_drag_plane.js +4 -0
  13. package/editor/view/ecs/EntityEditor.d.ts.map +1 -1
  14. package/editor/view/ecs/EntityEditor.js +3 -1
  15. package/editor/view/node-graph/NodeGraphView.d.ts.map +1 -1
  16. package/editor/view/node-graph/NodeGraphView.js +28 -12
  17. package/package.json +91 -96
  18. package/samples/engine/first-scene/index.html +4 -1
  19. package/samples/engine/first-scene/main.js +14 -9
  20. package/src/core/binary/utf8/utf8_decode.js +3 -3
  21. package/src/core/bvh2/binary/2/bvh32_query_user_data_ray.d.ts.map +1 -1
  22. package/src/core/bvh2/binary/2/bvh32_query_user_data_ray.js +112 -113
  23. package/src/core/bvh2/bvh3/ebvh_nodes_sort_sah_local4.js +2 -2
  24. package/src/core/cache/wtinylfu/benchmark/CacheWTinylfu.bench.md +14 -14
  25. package/src/core/collection/RingBuffer.d.ts.map +1 -1
  26. package/src/core/collection/RingBuffer.js +4 -0
  27. package/src/core/collection/array/array_contains_duplicates.d.ts.map +1 -1
  28. package/src/core/collection/array/array_contains_duplicates.js +2 -1
  29. package/src/core/collection/array/array_copy.d.ts.map +1 -1
  30. package/src/core/collection/array/array_copy.js +23 -0
  31. package/src/core/collection/array/typed/sparse_typed_array_hash.d.ts +2 -2
  32. package/src/core/collection/array/typed/sparse_typed_array_hash.d.ts.map +1 -1
  33. package/src/core/collection/array/typed/sparse_typed_array_hash.js +9 -8
  34. package/src/core/collection/array/typed/uint16_array_hash.d.ts +2 -2
  35. package/src/core/collection/array/typed/uint16_array_hash.js +4 -4
  36. package/src/core/collection/array/typed/uint8_array_hash.d.ts +2 -2
  37. package/src/core/collection/array/typed/uint8_array_hash.js +4 -4
  38. package/src/core/collection/array/weightedRandomFromArray.d.ts +1 -0
  39. package/src/core/collection/array/weightedRandomFromArray.d.ts.map +1 -1
  40. package/src/core/collection/array/weightedRandomFromArray.js +9 -1
  41. package/src/core/collection/heap/BinaryHeap.d.ts.map +1 -1
  42. package/src/core/collection/heap/BinaryHeap.js +4 -0
  43. package/src/core/collection/list/List.d.ts.map +1 -1
  44. package/src/core/collection/list/List.js +4 -2
  45. package/src/core/collection/set/ArraySet.js +1 -1
  46. package/src/core/collection/set/HashSet.d.ts +1 -1
  47. package/src/core/collection/set/HashSet.d.ts.map +1 -1
  48. package/src/core/collection/set/HashSet.js +4 -2
  49. package/src/core/debug/matchers/IsEqual.js +1 -1
  50. package/src/core/debug/matchers/IsIterableContaining.d.ts.map +1 -1
  51. package/src/core/debug/matchers/IsIterableContaining.js +61 -74
  52. package/src/core/events/signal/SignalBinding.js +101 -101
  53. package/src/core/function/extractFunctionBody.js +13 -13
  54. package/src/core/function/objectsEqual.d.ts.map +1 -1
  55. package/src/core/function/objectsEqual.js +15 -14
  56. package/src/core/geom/3d/frustum/frustum3_compute_closest_point.d.ts.map +1 -1
  57. package/src/core/geom/3d/frustum/frustum3_compute_closest_point.js +207 -172
  58. package/src/core/geom/3d/gjk/gjk_epa_penetration.d.ts.map +1 -1
  59. package/src/core/geom/3d/gjk/gjk_epa_penetration.js +5 -4
  60. package/src/core/geom/3d/line/line3_compute_segment_point_distance_eikonal.d.ts.map +1 -1
  61. package/src/core/geom/3d/line/line3_compute_segment_point_distance_eikonal.js +8 -2
  62. package/src/core/geom/3d/triangle/tri3_ray_intersection.d.ts +20 -0
  63. package/src/core/geom/3d/triangle/tri3_ray_intersection.d.ts.map +1 -1
  64. package/src/core/geom/3d/triangle/tri3_ray_intersection.js +182 -0
  65. package/src/core/math/noise/curl_noise_3dt.d.ts.map +1 -1
  66. package/src/core/math/noise/curl_noise_3dt.js +20 -10
  67. package/src/core/math/noise/sdnoise.d.ts +16 -5
  68. package/src/core/math/noise/sdnoise.d.ts.map +1 -1
  69. package/src/core/math/noise/sdnoise.js +43 -9
  70. package/src/core/math/spline/spline3_hermite_nearest_point.d.ts +16 -1
  71. package/src/core/math/spline/spline3_hermite_nearest_point.d.ts.map +1 -1
  72. package/src/core/math/spline/spline3_hermite_nearest_point.js +44 -3
  73. package/src/engine/Engine.d.ts.map +1 -1
  74. package/src/engine/Engine.js +6 -2
  75. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts +9 -0
  76. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts.map +1 -1
  77. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts +26 -0
  78. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts.map +1 -1
  79. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.js +2 -0
  80. package/src/engine/control/first-person/abilities/AbilitySet.d.ts.map +1 -1
  81. package/src/engine/control/first-person/abilities/AbilitySet.js +9 -0
  82. package/src/engine/control/first-person/abilities/LedgeGrab.d.ts.map +1 -1
  83. package/src/engine/control/first-person/abilities/LedgeGrab.js +6 -0
  84. package/src/engine/control/first-person/abilities/Slide.d.ts.map +1 -1
  85. package/src/engine/control/first-person/abilities/Slide.js +1 -0
  86. package/src/engine/control/first-person/abilities/WallRun.d.ts +4 -1
  87. package/src/engine/control/first-person/abilities/WallRun.d.ts.map +1 -1
  88. package/src/engine/control/first-person/abilities/WallRun.js +13 -1
  89. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.d.ts +1 -1
  90. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.d.ts.map +1 -1
  91. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.js +6 -5
  92. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.d.ts +3 -3
  93. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.d.ts.map +1 -1
  94. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.js +9 -8
  95. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts.map +1 -1
  96. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.js +13 -4
  97. package/src/engine/ecs/EntityManager.d.ts.map +1 -1
  98. package/src/engine/ecs/EntityManager.js +18 -15
  99. package/src/engine/ecs/dynamic_actions/rules/DynamicRuleDescription.d.ts.map +1 -1
  100. package/src/engine/ecs/dynamic_actions/rules/DynamicRuleDescription.js +2 -1
  101. package/src/engine/ecs/dynamic_actions/rules/DynamicRuleDescriptionTable.d.ts.map +1 -1
  102. package/src/engine/ecs/dynamic_actions/rules/DynamicRuleDescriptionTable.js +1 -0
  103. package/src/engine/ecs/fow/FogOfWarRevealerSystem.d.ts.map +1 -1
  104. package/src/engine/ecs/fow/FogOfWarRevealerSystem.js +3 -0
  105. package/src/engine/ecs/parent/EntityNode.js +3 -3
  106. package/src/engine/ecs/speaker/VoiceSystem.d.ts.map +1 -1
  107. package/src/engine/ecs/speaker/VoiceSystem.js +4 -0
  108. package/src/engine/ecs/storage/BinaryBufferDeSerializer.js +5 -5
  109. package/src/engine/ecs/storage/binary/BinarySerializationRegistry.d.ts.map +1 -1
  110. package/src/engine/ecs/storage/binary/BinarySerializationRegistry.js +3 -2
  111. package/src/engine/ecs/storage/binary/object/BinaryObjectSerializationAdapter2.js +1 -1
  112. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectDeSerializer.d.ts.map +1 -1
  113. package/src/engine/ecs/storage/binary/object-v2/BinaryObjectDeSerializer.js +8 -1
  114. package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
  115. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +8 -0
  116. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.d.ts.map +1 -1
  117. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSystem.js +5 -2
  118. package/src/engine/ecs/terrain/ecs/layers/TerrainLayers.d.ts.map +1 -1
  119. package/src/engine/ecs/terrain/ecs/layers/TerrainLayers.js +3 -0
  120. package/src/engine/ecs/terrain/ecs/splat/SplatMapping.d.ts.map +1 -1
  121. package/src/engine/ecs/terrain/ecs/splat/SplatMapping.js +1 -0
  122. package/src/engine/ecs/terrain/overlay/TerrainOverlay.js +1 -1
  123. package/src/engine/ecs/terrain/tiles/TerrainTile.d.ts.map +1 -1
  124. package/src/engine/ecs/terrain/tiles/TerrainTile.js +13 -1
  125. package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts.map +1 -1
  126. package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +1 -0
  127. package/src/engine/graphics/ecs/light/LightSerializationAdapter.d.ts.map +1 -1
  128. package/src/engine/graphics/ecs/light/LightSerializationAdapter.js +13 -1
  129. package/src/engine/graphics/ecs/light/LightSerializationUpgrader_0_1.d.ts +5 -0
  130. package/src/engine/graphics/ecs/light/LightSerializationUpgrader_0_1.d.ts.map +1 -0
  131. package/src/engine/graphics/ecs/light/LightSerializationUpgrader_0_1.js +27 -0
  132. package/src/engine/graphics/ecs/water/Water.d.ts +11 -0
  133. package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
  134. package/src/engine/graphics/ecs/water/Water.js +17 -0
  135. package/src/engine/graphics/ecs/water/WaterSerializationAdapter.d.ts.map +1 -1
  136. package/src/engine/graphics/ecs/water/WaterSerializationAdapter.js +3 -1
  137. package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_4_5.d.ts +9 -0
  138. package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_4_5.d.ts.map +1 -0
  139. package/src/engine/graphics/ecs/water/WaterSerializationUpgrader_4_5.js +24 -0
  140. package/src/engine/graphics/ecs/water/WaterWaves.d.ts +30 -9
  141. package/src/engine/graphics/ecs/water/WaterWaves.d.ts.map +1 -1
  142. package/src/engine/graphics/ecs/water/WaterWaves.js +41 -9
  143. package/src/engine/graphics/ecs/water/WaterWavesSerializationAdapter.d.ts.map +1 -1
  144. package/src/engine/graphics/ecs/water/WaterWavesSerializationAdapter.js +30 -26
  145. package/src/engine/graphics/ecs/water/WaterWavesSerializationUpgrader_0_1.d.ts +6 -0
  146. package/src/engine/graphics/ecs/water/WaterWavesSerializationUpgrader_0_1.d.ts.map +1 -0
  147. package/src/engine/graphics/ecs/water/WaterWavesSerializationUpgrader_0_1.js +22 -0
  148. package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_raycast.d.ts.map +1 -1
  149. package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_raycast.js +3 -5
  150. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.d.ts +20 -0
  151. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.d.ts.map +1 -1
  152. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.js +36 -0
  153. package/src/engine/graphics3/WaterSystem.d.ts +12 -3
  154. package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
  155. package/src/engine/graphics3/WaterSystem.js +78 -46
  156. package/src/engine/input/devices/PointerDevice.d.ts.map +1 -1
  157. package/src/engine/input/devices/PointerDevice.js +29 -4
  158. package/src/engine/intelligence/behavior/selector/WeightedRandomBehavior.d.ts +1 -0
  159. package/src/engine/intelligence/behavior/selector/WeightedRandomBehavior.d.ts.map +1 -1
  160. package/src/engine/intelligence/behavior/selector/WeightedRandomBehavior.js +14 -3
  161. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  162. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.d.ts.map +1 -1
  163. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.js +12 -3
  164. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.d.ts.map +1 -1
  165. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.js +8 -2
  166. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.d.ts +19 -0
  167. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.d.ts.map +1 -1
  168. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.js +41 -2
  169. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.d.ts.map +1 -1
  170. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.js +9 -3
  171. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.d.ts.map +1 -1
  172. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.js +26 -10
  173. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.d.ts +3 -6
  174. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.d.ts.map +1 -1
  175. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.js +22 -9
  176. package/src/engine/ui/DraggableAspect.d.ts +5 -1
  177. package/src/engine/ui/DraggableAspect.d.ts.map +1 -1
  178. package/src/engine/ui/DraggableAspect.js +61 -4
  179. package/src/format/image/avif/heif/ItemProperty.d.ts +1 -1
  180. package/src/format/image/avif/heif/ItemProperty.js +1 -1
  181. package/src/format/image/png/chunk/png_chunk_decode_iTXt.d.ts.map +1 -1
  182. package/src/format/image/png/chunk/png_chunk_decode_iTXt.js +17 -6
  183. package/src/shade/device/mock/SoftwareGPUDevice.d.ts +2 -4
  184. package/src/shade/device/mock/SoftwareGPUDevice.d.ts.map +1 -1
  185. package/src/shade/device/mock/SoftwareGPUDevice.js +20 -13
  186. package/src/shade/playground/skinned_blas_refit/sweep_views.d.ts.map +1 -1
  187. package/src/shade/playground/skinned_blas_refit/sweep_views.js +2 -1
  188. package/src/shade/playground/vgeo_runtime/README.md +5 -4
  189. package/src/shade/playground/water_refraction/README.md +10 -11
  190. package/src/shade/playground/water_refraction/main.js +9 -8
  191. package/src/shade/playground/water_refraction/world.js +1 -1
  192. package/src/shade/playground/water_surface/README.md +43 -0
  193. package/src/shade/playground/water_surface/index.html +30 -0
  194. package/src/shade/playground/water_surface/main.d.ts +2 -0
  195. package/src/shade/playground/water_surface/main.d.ts.map +1 -0
  196. package/src/shade/playground/water_surface/main.js +154 -0
  197. package/src/shade/playground/water_surface/world.d.ts +44 -0
  198. package/src/shade/playground/water_surface/world.d.ts.map +1 -0
  199. package/src/shade/playground/water_surface/world.js +160 -0
  200. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  201. package/src/shade/renderer/Renderer.js +6 -5
  202. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  203. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +5 -0
  204. package/src/shade/renderer/atmosphere/GPUSky.d.ts +12 -0
  205. package/src/shade/renderer/atmosphere/GPUSky.d.ts.map +1 -1
  206. package/src/shade/renderer/atmosphere/GPUSky.js +162 -147
  207. package/src/shade/renderer/binding/BufferBinding.js +2 -2
  208. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts.map +1 -1
  209. package/src/shade/renderer/buffer/table/GPUTypedTable.js +5 -3
  210. package/src/shade/renderer/buffer/table/GPUTypedTableDescriptor.d.ts +10 -3
  211. package/src/shade/renderer/buffer/table/GPUTypedTableDescriptor.d.ts.map +1 -1
  212. package/src/shade/renderer/buffer/table/GPUTypedTableDescriptor.js +17 -9
  213. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts +3 -0
  214. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts.map +1 -1
  215. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.js +16 -0
  216. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts +2 -0
  217. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts.map +1 -1
  218. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.js +11 -0
  219. package/src/shade/renderer/geometry/meshlet/build/meshoptimizer/geometry_to_meshlets_meshoptimizer.d.ts +1 -1
  220. package/src/shade/renderer/geometry/meshlet/build/meshoptimizer/geometry_to_meshlets_meshoptimizer.d.ts.map +1 -1
  221. package/src/shade/renderer/geometry/meshlet/build/meshoptimizer/geometry_to_meshlets_meshoptimizer.js +9 -3
  222. package/src/shade/renderer/geometry/util/geometry_simplify_redundant_topology.d.ts.map +1 -1
  223. package/src/shade/renderer/geometry/util/geometry_simplify_redundant_topology.js +2 -2
  224. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
  225. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +85 -0
  226. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -1
  227. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +12 -6
  228. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.d.ts.map +1 -1
  229. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.js +7 -0
  230. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts.map +1 -1
  231. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.js +3 -1
  232. package/src/shade/renderer/lightmap/bake/shader_lightmap_denoise_sh.d.ts.map +1 -1
  233. package/src/shade/renderer/lightmap/bake/shader_lightmap_denoise_sh.js +10 -3
  234. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  235. package/src/shade/renderer/particles/DESIGN.md +13 -9
  236. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts +1 -1
  237. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.js +1 -1
  238. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  239. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts +3 -2
  240. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts.map +1 -1
  241. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.js +3 -2
  242. package/src/shade/renderer/scene/GPUSceneContext.d.ts +9 -1
  243. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  244. package/src/shade/renderer/scene/GPUSceneContext.js +23 -1
  245. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.js +2 -1
  246. package/src/shade/renderer/shader/chunk/math/fft/chunk_fft128_inverse.d.ts +13 -0
  247. package/src/shade/renderer/shader/chunk/math/fft/chunk_fft128_inverse.d.ts.map +1 -0
  248. package/src/shade/renderer/shader/chunk/math/fft/chunk_fft128_inverse.js +42 -0
  249. package/src/shade/renderer/shader/chunk/math/fft/chunk_fft128x4_inverse_workgroup.d.ts +15 -0
  250. package/src/shade/renderer/shader/chunk/math/fft/chunk_fft128x4_inverse_workgroup.d.ts.map +1 -0
  251. package/src/shade/renderer/shader/chunk/math/fft/chunk_fft128x4_inverse_workgroup.js +39 -0
  252. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
  253. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +2 -0
  254. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts +4 -1
  255. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
  256. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +74 -3
  257. package/src/shade/renderer/volumetrics/NOTES.md +1023 -957
  258. package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.d.ts +5 -4
  259. package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.d.ts.map +1 -1
  260. package/src/shade/renderer/volumetrics/chunk_volumetrics_irradiance_sh.js +5 -4
  261. package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.d.ts +1 -1
  262. package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.js +1 -1
  263. package/src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.d.ts +1 -1
  264. package/src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.js +1 -1
  265. package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.d.ts +41 -0
  266. package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.d.ts.map +1 -0
  267. package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.js +112 -0
  268. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +9 -23
  269. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
  270. package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +18 -126
  271. package/src/shade/renderer/volumetrics/shader_volumetrics_build_irradiance.d.ts +22 -0
  272. package/src/shade/renderer/volumetrics/shader_volumetrics_build_irradiance.d.ts.map +1 -0
  273. package/src/shade/renderer/volumetrics/shader_volumetrics_build_irradiance.js +228 -0
  274. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts.map +1 -1
  275. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.js +0 -53
  276. package/src/shade/renderer/water/GPUWaterRenderer.d.ts +15 -0
  277. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  278. package/src/shade/renderer/water/GPUWaterRenderer.js +110 -30
  279. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +16 -8
  280. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +1 -1
  281. package/src/shade/renderer/water/medium/GPUWaterBodies.js +31 -26
  282. package/src/shade/renderer/water/medium/shader_water_meshlets.d.ts +0 -1
  283. package/src/shade/renderer/water/medium/shader_water_meshlets.d.ts.map +1 -1
  284. package/src/shade/renderer/water/medium/shader_water_meshlets.js +1 -39
  285. package/src/shade/renderer/water/shader_water.d.ts +0 -1
  286. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  287. package/src/shade/renderer/water/shader_water.js +201 -72
  288. package/src/shade/renderer/water/surface/GPUWaterSurface.d.ts +70 -0
  289. package/src/shade/renderer/water/surface/GPUWaterSurface.d.ts.map +1 -0
  290. package/src/shade/renderer/water/surface/GPUWaterSurface.js +199 -0
  291. package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.d.ts +5 -2
  292. package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.d.ts.map +1 -1
  293. package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.js +32 -12
  294. package/src/shade/renderer/water/surface/chunk_water_surface_sample.d.ts +23 -0
  295. package/src/shade/renderer/water/surface/chunk_water_surface_sample.d.ts.map +1 -0
  296. package/src/shade/renderer/water/surface/chunk_water_surface_sample.js +227 -0
  297. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +65 -11
  298. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts.map +1 -1
  299. package/src/shade/renderer/water/surface/graph_water_tessellation.js +163 -28
  300. package/src/shade/renderer/water/surface/lod/WATER_LOD.d.ts +51 -0
  301. package/src/shade/renderer/water/surface/lod/WATER_LOD.d.ts.map +1 -0
  302. package/src/shade/renderer/water/surface/lod/WATER_LOD.js +95 -0
  303. package/src/shade/renderer/water/surface/lod/chunk_water_lod.d.ts +10 -0
  304. package/src/shade/renderer/water/surface/lod/chunk_water_lod.d.ts.map +1 -0
  305. package/src/shade/renderer/water/surface/lod/chunk_water_lod.js +127 -0
  306. package/src/shade/renderer/water/surface/lod/chunk_water_lod_cell.d.ts +17 -0
  307. package/src/shade/renderer/water/surface/lod/chunk_water_lod_cell.d.ts.map +1 -0
  308. package/src/shade/renderer/water/surface/lod/chunk_water_lod_cell.js +246 -0
  309. package/src/shade/renderer/water/surface/lod/shader_water_lod.d.ts +118 -0
  310. package/src/shade/renderer/water/surface/lod/shader_water_lod.d.ts.map +1 -0
  311. package/src/shade/renderer/water/surface/lod/shader_water_lod.js +727 -0
  312. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.d.ts +60 -0
  313. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.d.ts.map +1 -0
  314. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.js +274 -0
  315. package/src/shade/renderer/water/surface/particles/WATER_PARTICLE_STRUCT.d.ts +17 -0
  316. package/src/shade/renderer/water/surface/particles/WATER_PARTICLE_STRUCT.d.ts.map +1 -0
  317. package/src/shade/renderer/water/surface/particles/WATER_PARTICLE_STRUCT.js +57 -0
  318. package/src/shade/renderer/water/surface/particles/chunk_water_particle.d.ts +43 -0
  319. package/src/shade/renderer/water/surface/particles/chunk_water_particle.d.ts.map +1 -0
  320. package/src/shade/renderer/water/surface/particles/chunk_water_particle.js +268 -0
  321. package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.d.ts +20 -0
  322. package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.d.ts.map +1 -0
  323. package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.js +239 -0
  324. package/src/shade/renderer/water/surface/particles/shader_water_particles.d.ts +153 -0
  325. package/src/shade/renderer/water/surface/particles/shader_water_particles.d.ts.map +1 -0
  326. package/src/shade/renderer/water/surface/particles/shader_water_particles.js +874 -0
  327. package/src/shade/renderer/water/surface/shader_water_cull.d.ts +42 -0
  328. package/src/shade/renderer/water/surface/shader_water_cull.d.ts.map +1 -0
  329. package/src/shade/renderer/water/surface/shader_water_cull.js +269 -0
  330. package/src/shade/renderer/water/surface/shader_water_waves_combine.d.ts +15 -0
  331. package/src/shade/renderer/water/surface/shader_water_waves_combine.d.ts.map +1 -0
  332. package/src/shade/renderer/water/surface/shader_water_waves_combine.js +73 -0
  333. package/src/shade/renderer/water/surface/shader_water_waves_derive.d.ts +11 -0
  334. package/src/shade/renderer/water/surface/shader_water_waves_derive.d.ts.map +1 -0
  335. package/src/shade/renderer/water/surface/shader_water_waves_derive.js +78 -0
  336. package/src/shade/renderer/water/surface/spectrum/GPUWaterSpectrum.d.ts +35 -0
  337. package/src/shade/renderer/water/surface/spectrum/GPUWaterSpectrum.d.ts.map +1 -0
  338. package/src/shade/renderer/water/surface/spectrum/GPUWaterSpectrum.js +103 -0
  339. package/src/shade/renderer/water/surface/spectrum/WATER_BAND_STATE.d.ts +22 -0
  340. package/src/shade/renderer/water/surface/spectrum/WATER_BAND_STATE.d.ts.map +1 -0
  341. package/src/shade/renderer/water/surface/spectrum/WATER_BAND_STATE.js +57 -0
  342. package/src/shade/renderer/water/surface/spectrum/WATER_SPECTRUM.d.ts +22 -0
  343. package/src/shade/renderer/water/surface/spectrum/WATER_SPECTRUM.d.ts.map +1 -0
  344. package/src/shade/renderer/water/surface/spectrum/WATER_SPECTRUM.js +25 -0
  345. package/src/shade/renderer/water/surface/spectrum/chunk_water_jonswap.d.ts +14 -0
  346. package/src/shade/renderer/water/surface/spectrum/chunk_water_jonswap.d.ts.map +1 -0
  347. package/src/shade/renderer/water/surface/spectrum/chunk_water_jonswap.js +48 -0
  348. package/src/shade/renderer/water/surface/spectrum/chunk_water_spectrum.d.ts +23 -0
  349. package/src/shade/renderer/water/surface/spectrum/chunk_water_spectrum.d.ts.map +1 -0
  350. package/src/shade/renderer/water/surface/spectrum/chunk_water_spectrum.js +169 -0
  351. package/src/shade/renderer/water/surface/spectrum/shader_water_spectrum.d.ts +26 -0
  352. package/src/shade/renderer/water/surface/spectrum/shader_water_spectrum.d.ts.map +1 -0
  353. package/src/shade/renderer/water/surface/spectrum/shader_water_spectrum.js +161 -0
  354. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
  355. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +29 -9
  356. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  357. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +14 -3
  358. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.d.ts +0 -28
  359. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.d.ts.map +0 -1
  360. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.js +0 -86
  361. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.d.ts +0 -29
  362. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.d.ts.map +0 -1
  363. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.js +0 -44
  364. package/src/shade/renderer/water/medium/shader_water_bodies_derive.d.ts +0 -4
  365. package/src/shade/renderer/water/medium/shader_water_bodies_derive.d.ts.map +0 -1
  366. package/src/shade/renderer/water/medium/shader_water_bodies_derive.js +0 -32
  367. package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.d.ts +0 -25
  368. package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.d.ts.map +0 -1
  369. package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.js +0 -128
  370. package/src/shade/renderer/water/surface/chunk_water_tessellation.d.ts +0 -9
  371. package/src/shade/renderer/water/surface/chunk_water_tessellation.d.ts.map +0 -1
  372. package/src/shade/renderer/water/surface/chunk_water_tessellation.js +0 -144
  373. package/src/shade/renderer/water/surface/chunk_water_wave.d.ts +0 -13
  374. package/src/shade/renderer/water/surface/chunk_water_wave.d.ts.map +0 -1
  375. package/src/shade/renderer/water/surface/chunk_water_wave.js +0 -40
  376. package/src/shade/renderer/water/surface/shader_water_tiles.d.ts +0 -4
  377. package/src/shade/renderer/water/surface/shader_water_tiles.d.ts.map +0 -1
  378. package/src/shade/renderer/water/surface/shader_water_tiles.js +0 -123
  379. package/src/shade/renderer/water/surface/shader_water_wave_batch.d.ts +0 -6
  380. package/src/shade/renderer/water/surface/shader_water_wave_batch.d.ts.map +0 -1
  381. package/src/shade/renderer/water/surface/shader_water_wave_batch.js +0 -85
  382. package/src/shade/renderer/water/surface/shader_water_wave_domain.d.ts +0 -6
  383. package/src/shade/renderer/water/surface/shader_water_wave_domain.d.ts.map +0 -1
  384. package/src/shade/renderer/water/surface/shader_water_wave_domain.js +0 -83
@@ -0,0 +1,268 @@
1
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
2
+ import { chunk_pcg3d } from "../../../shader/chunk/random/pcg/chunk_pcg3d.js";
3
+ import { WATER_PARTICLE_ENTRY_STRUCT, WATER_PARTICLE_STRUCT } from "./WATER_PARTICLE_STRUCT.js";
4
+ import { chunk_water_spectrum } from "../spectrum/chunk_water_spectrum.js";
5
+
6
+ /**
7
+ * Levels of the particle hash: cell sizes 4 mm · 2^level, so supports up to 256 m, which a 2 m splash's stretched
8
+ * packets reach before they die.
9
+ */
10
+ export const WATER_PARTICLE_LEVELS = 18;
11
+
12
+ /** Bits of a hash key that hold the level, below the body's row. */
13
+ const WATER_PARTICLE_LEVEL_BITS = Math.ceil(Math.log2(WATER_PARTICLE_LEVELS));
14
+
15
+ /** Cell size of level 0, metres. A particle sits at the smallest level whose cell is at least its support's diameter. */
16
+ export const WATER_PARTICLE_LEVEL0_CELL = 1 / 256;
17
+
18
+ /**
19
+ * How fast a packet's envelope stretches as it disperses, as a fraction κ of its group speed, by its wavenumber k against
20
+ * k_m = √(g/(σ/ρ)), the wavenumber of the slowest crests (λ = 1.71 cm): from x = log₂(k/k_m) = -7 in steps of a quarter,
21
+ * held at both ends.
22
+ *
23
+ * Its half-length h, 2r when emitted, grows as h² = (2r)² + (κD/2)² over the distance D its front has travelled since:
24
+ * the spread of an unchirped packet's energy grows as the spread of its group speeds times time, in quadrature with
25
+ * where it began (Jeschke & Wojtan 2017 grow it linearly, eq. 14, its far limit). Each κ is the one whose peak
26
+ * √(2r/h) best matches exact linear theory, ω² = gk + (σ/ρ)k³, for the emitted packet at 5 to 225 wavelengths (FFT,
27
+ * worst ratio minimised): within 2% for capillary waves up to r = 8.5 mm and gravity waves from r = 6 cm, where κ
28
+ * tends to 1 and 0.9, and 5% from 4 cm. Between, around the slowest group speed (λ = 4.4 cm), a broad band's energy
29
+ * gathers at that speed and the peak falls as t^(−1/3), which no κ draws: up to 16% below r = 12 mm, 27% at 3 cm.
30
+ */
31
+ export const WATER_PARTICLE_STRETCH = [
32
+ 0.9002, 0.9002, 0.8998, 0.8993, 0.8984, 0.8971, 0.8957, 0.8935, 0.8904, 0.8859, 0.8798, 0.8706, 0.8585, 0.8411, 0.8166,
33
+ 0.7819, 0.7323, 0.6669, 0.5795, 0.461, 0.216, 0.0922, 0.064, 0.0723, 0.1089, 0.1877, 0.3427, 0.6145, 0.9295, 1.0417,
34
+ 1.0734, 1.0739, 1.0622, 1.0469, 1.0313, 1.0175, 1.0059, 0.9969, 0.9899,
35
+ ];
36
+
37
+ /** log₂(k/k_m) of the stretch table's first entry; entries are a quarter apart. */
38
+ const WATER_PARTICLE_STRETCH_FIRST = -7;
39
+
40
+ /**
41
+ * The physics of one wave particle as pure functions (WATER_SURFACE_SIMULATION_PLAN_2026_10_06.md §5).
42
+ *
43
+ * A particle of radius r carries a packet of wavelength 2r, k = π/r. Under the gravity–capillary
44
+ * dispersion relation the packet's envelope travels at the group speed and its crests at the phase speed
45
+ * (Jeschke & Wojtan 2017; Xue et al. 2025 give wave particles their own wavelength's dispersion). The packet holds a
46
+ * band of wavelengths around 2r, which the same relation moves apart: its envelope, two radii either side when emitted,
47
+ * stretches as it travels and its height falls to keep its energy (WATER_PARTICLE_STRETCH), as a splash's single ring
48
+ * becomes a widening train of ripples. It loses amplitude at the clean-surface viscous rate 2νk² plus the surface-film
49
+ * rate k√(νω)/(2√2) of natural water — so a raindrop's ripple is gone in a fraction of a second while a big splash
50
+ * crosses a bay.
51
+ *
52
+ * The particles of a front are β apart in angle around its centre, and a packet's crests are arcs around that
53
+ * centre; a cosine window of half-angle β is a partition of unity over them at every radius, so the front's
54
+ * height is the packet's amplitude whatever the spacing, splitting a front changes none of it, and one front
55
+ * adds at most two particles at any point.
56
+ *
57
+ * @type {CodeChunk}
58
+ */
59
+ export const chunk_water_particle = CodeChunk.from(/* language=WGSL */ `
60
+ const WATER_PARTICLE_LEVELS: u32 = ${WATER_PARTICLE_LEVELS}u;
61
+ const WATER_PARTICLE_LEVEL_BITS: u32 = ${WATER_PARTICLE_LEVEL_BITS}u;
62
+ const WATER_PARTICLE_LEVEL0_CELL: f32 = ${WATER_PARTICLE_LEVEL0_CELL};
63
+ const WATER_PARTICLE_STRETCH = array<f32, ${WATER_PARTICLE_STRETCH.length}>(${WATER_PARTICLE_STRETCH.join(', ')});
64
+ const WATER_PARTICLE_STRETCH_FIRST: f32 = ${WATER_PARTICLE_STRETCH_FIRST}.0;
65
+ // kinematic viscosity of water, m²/s
66
+ const WATER_VISCOSITY: f32 = 1e-6;
67
+ const WATER_PI: f32 = 3.14159265358979;
68
+
69
+ fn water_particle_wavenumber(radius: f32) -> f32 {
70
+ return WATER_PI / radius;
71
+ }
72
+
73
+ // Phase speed of the particle's wavelength, m/s: how fast its crests move.
74
+ fn water_particle_phase_speed(radius: f32) -> f32 {
75
+ let k = water_particle_wavenumber(radius);
76
+ return water_dispersion(k) / k;
77
+ }
78
+
79
+ // Group speed dω/dk of the particle's wavelength, m/s: how fast its packet moves.
80
+ fn water_particle_group_speed(radius: f32) -> f32 {
81
+ let k = water_particle_wavenumber(radius);
82
+ return (WATER_GRAVITY + 3.0 * WATER_SURFACE_TENSION * k * k) / (2.0 * water_dispersion(k));
83
+ }
84
+
85
+ // Amplitude decay rate, 1/s: viscous plus surface film.
86
+ fn water_particle_damping(radius: f32) -> f32 {
87
+ let k = water_particle_wavenumber(radius);
88
+ return 2.0 * WATER_VISCOSITY * k * k + k * sqrt(WATER_VISCOSITY * water_dispersion(k)) / (2.0 * sqrt(2.0));
89
+ }
90
+
91
+ fn water_particle_direction(angle: f32) -> vec2<f32> {
92
+ return vec2<f32>(cos(angle), sin(angle));
93
+ }
94
+
95
+ // Distance the front has travelled from its origin.
96
+ fn water_particle_distance(particle: ${WATER_PARTICLE_STRUCT.wgsl_ref}) -> f32 {
97
+ return water_particle_group_speed(particle.radius) * particle.age;
98
+ }
99
+
100
+ fn water_particle_position(particle: ${WATER_PARTICLE_STRUCT.wgsl_ref}) -> vec2<f32> {
101
+ return particle.origin + water_particle_direction(particle.angle) * water_particle_distance(particle);
102
+ }
103
+
104
+ // The front's arc between neighbouring particles, at the particle's own radius: what the window spans there.
105
+ fn water_particle_width(particle: ${WATER_PARTICLE_STRUCT.wgsl_ref}) -> f32 {
106
+ return max(particle.dispersion * water_particle_distance(particle), 1e-3 * particle.radius);
107
+ }
108
+
109
+ // How far the crests have slid through the envelope: k (c − c_g) age.
110
+ fn water_particle_phase(particle: ${WATER_PARTICLE_STRUCT.wgsl_ref}) -> f32 {
111
+ let lag = (water_particle_phase_speed(particle.radius) - water_particle_group_speed(particle.radius)) * particle.age;
112
+ return water_particle_wavenumber(particle.radius) * lag;
113
+ }
114
+
115
+ // How far from a splash's centre its ring starts: two radii, the packet's half-length, so it starts clear of the centre.
116
+ fn water_particle_launch_distance(radius: f32) -> f32 {
117
+ return 2.0 * radius;
118
+ }
119
+
120
+ // How fast the packet's envelope stretches, as a fraction of its group speed (WATER_PARTICLE_STRETCH): interpolated in
121
+ // log κ between quarter octaves of k against the wavenumber of the slowest crests.
122
+ fn water_particle_stretch(radius: f32) -> f32 {
123
+ let octave = log2(water_particle_wavenumber(radius) * sqrt(WATER_SURFACE_TENSION / WATER_GRAVITY));
124
+ let last = f32(${WATER_PARTICLE_STRETCH.length}u - 1u);
125
+ let t = clamp(4.0 * (octave - WATER_PARTICLE_STRETCH_FIRST), 0.0, last);
126
+ let i = u32(min(floor(t), last - 1.0));
127
+ return exp2(mix(log2(WATER_PARTICLE_STRETCH[i]), log2(WATER_PARTICLE_STRETCH[i + 1u]), t - f32(i)));
128
+ }
129
+
130
+ // Half the length of the packet's envelope across its front, for a front that stands distance from its centre: 2r when
131
+ // emitted, growing in quadrature with half the stretch over the distance travelled since. Held to half the largest support
132
+ // the hash holds, so a window no wider keeps the packet within the coarsest cells.
133
+ fn water_particle_half_length_at(radius: f32, distance: f32) -> f32 {
134
+ let travelled = max(distance - water_particle_launch_distance(radius), 0.0);
135
+ let stretched = length(vec2<f32>(2.0 * radius, 0.5 * water_particle_stretch(radius) * travelled));
136
+ return min(stretched, 0.5 * water_particle_support_limit());
137
+ }
138
+
139
+ fn water_particle_half_length(particle: ${WATER_PARTICLE_STRUCT.wgsl_ref}) -> f32 {
140
+ return water_particle_half_length_at(particle.radius, water_particle_distance(particle));
141
+ }
142
+
143
+ // Radius of a circle around the particle holding its whole kernel: the envelope's half-length h across the front, and
144
+ // along it the front's arc of half-angle β plus its outer edge's overhang. A point at radius ρ = D + u and angle ψ from
145
+ // a particle at distance D lies |d|² = u² + 4ρD·sin²(ψ/2) ≤ h² + (D + h)Dβ² ≤ h² + ((D + h/2)β)² from it, and
146
+ // width ≥ Dβ.
147
+ fn water_particle_support(half_length: f32, width: f32, dispersion: f32) -> f32 {
148
+ return length(vec2<f32>(half_length, width + 0.5 * half_length * dispersion));
149
+ }
150
+
151
+ // The largest support the hash holds: half its coarsest cell.
152
+ fn water_particle_support_limit() -> f32 {
153
+ return 0.5 * water_particle_cell_size(WATER_PARTICLE_LEVELS - 1u);
154
+ }
155
+
156
+ // Whether two particles are of one front: one splash's, neither reflected or faded apart, alike in all but angle.
157
+ fn water_particle_same_front(a: ${WATER_PARTICLE_STRUCT.wgsl_ref}, b: ${WATER_PARTICLE_STRUCT.wgsl_ref}) -> bool {
158
+ return a.body == b.body && all(a.origin == b.origin) && a.age == b.age && a.amplitude == b.amplitude
159
+ && a.radius == b.radius && a.dispersion == b.dispersion;
160
+ }
161
+
162
+ // How a particle is drawn, given its front's run of particles in the array and its place in it: 1 as itself; 0 not at
163
+ // all, or a group of 3^g as one packet with 3^g times its window, when its front is whole. Whole is every particle
164
+ // the front split into still there, in order and alike: as many as fill its circle. The step puts a particle's three
165
+ // in its place, the middle at its own angle, so a group of 3^g is 3^g in a row and its middle stands at the angle
166
+ // the group was emitted at; with curved crests the groups draw what the particles do. The largest group whose packet
167
+ // the hash holds: the seven a front was emitted as, until their windows outgrow the coarsest cell.
168
+ fn water_particle_group(particle: ${WATER_PARTICLE_STRUCT.wgsl_ref}, members: u32, offset: u32) -> u32 {
169
+ if (members != u32(round(WATER_TAU / particle.dispersion))) { return 1u; }
170
+ var group = 1u;
171
+ for (var g = 0u; g < 20u && members % (3u * group) == 0u; g++) { group *= 3u; }
172
+ let distance = water_particle_distance(particle);
173
+ let half_length = water_particle_half_length_at(particle.radius, distance);
174
+ for (var g = 0u; g < 20u && group > 1u; g++) {
175
+ let dispersion = particle.dispersion * f32(group);
176
+ let width = max(dispersion * distance, 1e-3 * particle.radius);
177
+ if (water_particle_support(half_length, width, dispersion) <= water_particle_support_limit()) { break; }
178
+ group /= 3u;
179
+ }
180
+ return select(0u, group, offset % group == group / 2u);
181
+ }
182
+
183
+ // The particle as its group draws it: one packet with the group's window.
184
+ fn water_particle_drawn(particle: ${WATER_PARTICLE_STRUCT.wgsl_ref}, group: u32) -> ${WATER_PARTICLE_STRUCT.wgsl_ref} {
185
+ var drawn = particle;
186
+ drawn.dispersion *= f32(group);
187
+ return drawn;
188
+ }
189
+
190
+ // The smallest hash level whose cell is at least the support's diameter, so the support overlaps at most
191
+ // the 2×2 cells around it.
192
+ fn water_particle_level(support: f32) -> u32 {
193
+ let level = ceil(log2(max(2.0 * support / WATER_PARTICLE_LEVEL0_CELL, 1.0)));
194
+ return min(u32(level), WATER_PARTICLE_LEVELS - 1u);
195
+ }
196
+
197
+ fn water_particle_cell_size(level: u32) -> f32 {
198
+ return WATER_PARTICLE_LEVEL0_CELL * exp2(f32(level));
199
+ }
200
+
201
+ // A hash entry's body and level in one word.
202
+ fn water_particle_key(body: u32, level: u32) -> u32 {
203
+ return (body << WATER_PARTICLE_LEVEL_BITS) | level;
204
+ }
205
+
206
+ fn water_particle_bucket(body: u32, level: u32, cell: vec2<i32>, table_size: u32) -> u32 {
207
+ let bits = pcg3d(vec3<u32>(water_particle_key(body, level), bitcast<u32>(cell.x), bitcast<u32>(cell.y)));
208
+ return bits.x & (table_size - 1u);
209
+ }
210
+
211
+ struct WaterParticleField {
212
+ height: f32,
213
+ // ∂h/∂x, ∂h/∂z
214
+ slope: vec2<f32>,
215
+ displacement: vec2<f32>,
216
+ // columns ∂D/∂x and ∂D/∂z: (∂Dx/∂x, ∂Dz/∂x), (∂Dx/∂z, ∂Dz/∂z)
217
+ jacobian: mat2x2<f32>,
218
+ // the gradient of the displacement's signed length along the radius: the slope a quarter carrier cycle on, so that
219
+ // ½(|slope|² + |this|²) is the slope's mean square over a cycle
220
+ displacement_gradient: vec2<f32>,
221
+ }
222
+
223
+ // The packet at offset d from its particle, which stands distance from its front's centre. ρ the radius from the
224
+ // centre and u = ρ − distance across the front, ψ the angle around the centre from the particle's direction:
225
+ // envelope E(u) over half_length either side, window T(ψ) over the dispersion β either side, carrier phase πu/r − phase.
226
+ // Height a·E·T·cos; horizontal displacement −a·E·T·sin along the radius (Gerstner-like orbits, Yuksel's longitudinal
227
+ // sign); with derivatives, ∇ψ = e_ψ/ρ.
228
+ fn water_particle_field(d: vec2<f32>, angle: f32, amplitude: f32, radius: f32, half_length: f32, dispersion: f32, distance: f32,
229
+ phase: f32) -> WaterParticleField {
230
+ var field: WaterParticleField;
231
+ let direction = water_particle_direction(angle);
232
+ let tangent = vec2<f32>(-direction.y, direction.x);
233
+ let q = d + direction * distance;
234
+ let rho = length(q);
235
+ // ρ − distance, without the cancellation
236
+ let u = (dot(d, d) + 2.0 * distance * dot(d, direction)) / max(rho + distance, 1e-30);
237
+ if (abs(u) >= half_length || !(rho > 0.0)) { return field; }
238
+ let psi = atan2(dot(d, tangent), distance + dot(d, direction));
239
+ if (abs(psi) >= dispersion) { return field; }
240
+ let radial = q / rho;
241
+ let around = vec2<f32>(-radial.y, radial.x);
242
+ let eu = WATER_PI * u / half_length;
243
+ let envelope = 0.5 * (1.0 + cos(eu));
244
+ let envelope_du = -0.5 * WATER_PI / half_length * sin(eu);
245
+ let tv = WATER_PI * psi / dispersion;
246
+ let window = 0.5 * (1.0 + cos(tv));
247
+ let window_dpsi = -0.5 * WATER_PI / dispersion * sin(tv);
248
+ let carrier = WATER_PI * u / radius - phase;
249
+ let c = cos(carrier);
250
+ let s = sin(carrier);
251
+ let k = WATER_PI / radius;
252
+ let z = amplitude * envelope * window * c;
253
+ let z_u = amplitude * window * (envelope_du * c - envelope * s * k);
254
+ let z_psi = amplitude * envelope * window_dpsi * c;
255
+ let h = -amplitude * envelope * window * s;
256
+ let h_u = -amplitude * window * (envelope_du * s + envelope * c * k);
257
+ let h_psi = -amplitude * envelope * window_dpsi * s;
258
+ let gradient_h = h_u * radial + (h_psi / rho) * around;
259
+ // the radius turns as the point moves around the centre: ∂e_ρ/∂x_j = e_ψ (e_ψ)_j / ρ
260
+ let turn = (h / rho) * around;
261
+ field.height = z;
262
+ field.slope = z_u * radial + (z_psi / rho) * around;
263
+ field.displacement = h * radial;
264
+ field.jacobian = mat2x2<f32>(radial * gradient_h.x + turn * around.x, radial * gradient_h.y + turn * around.y);
265
+ field.displacement_gradient = gradient_h;
266
+ return field;
267
+ }
268
+ `, [chunk_water_spectrum, chunk_pcg3d, WATER_PARTICLE_STRUCT.declaration_chunk, WATER_PARTICLE_ENTRY_STRUCT.declaration_chunk]);
@@ -0,0 +1,20 @@
1
+ /** Seconds over which a packet that has fallen below the drawing threshold fades to a tenth of it, where it dies. */
2
+ export const WATER_PARTICLE_FADE_SECONDS: 0.15;
3
+ /**
4
+ * One frame of one wave particle (WATER_SURFACE_SIMULATION_PLAN_2026_10_06.md §5.1): it ages, spreads over its
5
+ * widening front, damps, meets its body's authored outline, and dies or splits.
6
+ *
7
+ * At the outline the water shows the packet plus the shore's share of its mirror image in the outline (the image
8
+ * method, as Jeschke & Wojtan 2017 §4.4 keep a "ghost" of a reflected packet): the image is emitted the step the first
9
+ * of the packet's support leaves the body, and the packet carries on until the last of it has left it too. The body's
10
+ * outline clips what of either lies beyond it, so the water changes only as the two move.
11
+ *
12
+ * Whether a point is over the body is a down-ray into the body's own BLAS, so the outline is exactly the
13
+ * authored mesh's, holes for islands included. Bindings: `geometries`, `blas_lookup`, `blas_data`,
14
+ * `meshlet_metadata`, `meshlet_data`.
15
+ *
16
+ * @type {CodeChunk}
17
+ */
18
+ export const chunk_water_particle_step: CodeChunk;
19
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
20
+ //# sourceMappingURL=chunk_water_particle_step.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_water_particle_step.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/water/surface/particles/chunk_water_particle_step.js"],"names":[],"mappings":"AAQA,qHAAqH;AACrH,+CAAgD;AAEhD;;;;;;;;;;;;;;GAcG;AACH,wCAFU,SAAS,CAsN8E;0BA9OvE,uCAAuC"}
@@ -0,0 +1,239 @@
1
+ import { CodeChunk } from "../../../shader/compiler/CodeChunk.js";
2
+ import { BVH_TRAVERSAL_STACK_SIZE } from "../../../shader/chunk/bvh/BVH_TRAVERSAL_STACK_SIZE.js";
3
+ import { chunk_ray_query_blas_nearest } from "../../../shader/chunk/geometry/ray/chunk_ray_query_blas_nearest.js";
4
+ import { chunk_geometry_read_triangle_positions } from "../../../shader/chunk/geometry/format/chunk_geometry_read_triangle_positions.js";
5
+ import { RAY_HIT_INFO } from "../../../shader/chunk/geometry/ray/RAY_HIT_INFO.js";
6
+ import { WATER_PARTICLE_STRUCT } from "./WATER_PARTICLE_STRUCT.js";
7
+ import { chunk_water_particle } from "./chunk_water_particle.js";
8
+
9
+ /** Seconds over which a packet that has fallen below the drawing threshold fades to a tenth of it, where it dies. */
10
+ export const WATER_PARTICLE_FADE_SECONDS = 0.15;
11
+
12
+ /**
13
+ * One frame of one wave particle (WATER_SURFACE_SIMULATION_PLAN_2026_10_06.md §5.1): it ages, spreads over its
14
+ * widening front, damps, meets its body's authored outline, and dies or splits.
15
+ *
16
+ * At the outline the water shows the packet plus the shore's share of its mirror image in the outline (the image
17
+ * method, as Jeschke & Wojtan 2017 §4.4 keep a "ghost" of a reflected packet): the image is emitted the step the first
18
+ * of the packet's support leaves the body, and the packet carries on until the last of it has left it too. The body's
19
+ * outline clips what of either lies beyond it, so the water changes only as the two move.
20
+ *
21
+ * Whether a point is over the body is a down-ray into the body's own BLAS, so the outline is exactly the
22
+ * authored mesh's, holes for islands included. Bindings: `geometries`, `blas_lookup`, `blas_data`,
23
+ * `meshlet_metadata`, `meshlet_data`.
24
+ *
25
+ * @type {CodeChunk}
26
+ */
27
+ export const chunk_water_particle_step = CodeChunk.from(/* language=WGSL */ `
28
+ const WATER_PARTICLE_FADE_SECONDS: f32 = ${WATER_PARTICLE_FADE_SECONDS};
29
+
30
+ struct WaterParticleStep {
31
+ // the particle a step on
32
+ particle: ${WATER_PARTICLE_STRUCT.wgsl_ref},
33
+ // the mirror image it leaves, when it leaves one
34
+ image: ${WATER_PARTICLE_STRUCT.wgsl_ref},
35
+ // the particles it leaves, each split into three when they split: 0, 1, 2 (it, then its image), 3 or 6
36
+ children: u32,
37
+ }
38
+
39
+ // The body's surface under a point of its local xz, or a miss (t < 0) off its outline.
40
+ fn water_particle_over_body(geometry_index: u32, local: vec2<f32>) -> ${RAY_HIT_INFO.wgsl_ref} {
41
+ let box = geometries[geometry_index].bounding_box;
42
+ let margin = max(1e-3, (box[4] - box[1]) * 1e-4);
43
+ let top = box[4] + margin;
44
+ var stack: array<u32, ${BVH_TRAVERSAL_STACK_SIZE}>;
45
+ return ray_query_blas_nearest(Ray(vec3<f32>(local.x, top, local.y), vec3<f32>(0.0, -1.0, 0.0),
46
+ top - box[1] + margin), geometry_index, &stack, 0u);
47
+ }
48
+
49
+ // The points of a packet's support the step tests against the outline, on its arc ρ from its front's centre: the k-th
50
+ // of its axis and its window's ends, β either side of it. The support is the annular sector of two radii either side of
51
+ // the front and β either side of the axis, so a straight outline meets first the point of its leading arc whose
52
+ // direction is nearest the outline's normal, an end unless the normal is within β of the axis, and leaves last the end
53
+ // of its trailing arc farthest from it: at any incidence, these three find both, or within the arc's sagitta.
54
+ fn water_particle_support_point(particle: ${WATER_PARTICLE_STRUCT.wgsl_ref}, k: u32, rho: f32) -> vec2<f32> {
55
+ let turn = select(0.0, select(particle.dispersion, -particle.dispersion, k == 1u), k > 0u);
56
+ return particle.origin + water_particle_direction(particle.angle + turn) * rho;
57
+ }
58
+
59
+ // Whether a triangle seen from above holds a point strictly inside it, in the body's local xz.
60
+ fn water_triangle_covers(a: vec2<f32>, b: vec2<f32>, c: vec2<f32>, point: vec2<f32>) -> bool {
61
+ let side = sign((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x));
62
+ let ab = (b.x - a.x) * (point.y - a.y) - (b.y - a.y) * (point.x - a.x);
63
+ let bc = (c.x - b.x) * (point.y - b.y) - (c.y - b.y) * (point.x - b.x);
64
+ let ca = (a.x - c.x) * (point.y - c.y) - (a.y - c.y) * (point.x - c.x);
65
+ return side * ab > 0.0 && side * bc > 0.0 && side * ca > 0.0;
66
+ }
67
+
68
+ // The k-th tested point of a particle's leading arc once it has stepped dt on: what water_particle_advance tests.
69
+ fn water_particle_leading_point(particle: ${WATER_PARTICLE_STRUCT.wgsl_ref}, dt: f32, k: u32) -> vec2<f32> {
70
+ var stepped = particle;
71
+ stepped.age += dt;
72
+ return water_particle_support_point(stepped, k, water_particle_distance(stepped) + water_particle_half_length(stepped));
73
+ }
74
+
75
+ // What is already known of a particle's leading arc a step on, bit k for its k-th tested point: whether that is known,
76
+ // and whether it is over the body; and the triangle under the axis's point when that is. Zero is nothing known. A
77
+ // particle's window's ends are its neighbours' axis points when they are of its front, so the update pass hands each
78
+ // what its neighbours in the subgroup found.
79
+ struct WaterParticleArcHint {
80
+ known: u32,
81
+ over: u32,
82
+ triangle: u32,
83
+ }
84
+
85
+ // Whether any of an arc's tested points is over the body.
86
+ fn water_particle_arc_over(particle: ${WATER_PARTICLE_STRUCT.wgsl_ref}, geometry_index: u32, scale: vec2<f32>, rho: f32) -> bool {
87
+ for (var k = 0u; k < 3u; k++) {
88
+ if (water_particle_over_body(geometry_index, water_particle_support_point(particle, k, rho) / scale).t >= 0.0) { return true; }
89
+ }
90
+ return false;
91
+ }
92
+
93
+ // The line of the edge of a triangle nearest a point inside it, in the metric xz frame: a point on it and a
94
+ // unit normal. Which side the normal points to does not matter: a mirror in a line is the same for either.
95
+ struct WaterOutlineLine {
96
+ point: vec2<f32>,
97
+ normal: vec2<f32>,
98
+ }
99
+
100
+ fn water_outline_line(geometry_index: u32, triangle: u32, point: vec2<f32>, scale: vec2<f32>) -> WaterOutlineLine {
101
+ let vertices = geometry_read_triangle_vertices(geometries[geometry_index], triangle);
102
+ let corners = array<vec2<f32>, 3>(vertices.a.position.xz * scale, vertices.b.position.xz * scale, vertices.c.position.xz * scale);
103
+ var nearest = 3.0e38;
104
+ var line = WaterOutlineLine(point, vec2<f32>(0.0));
105
+ for (var edge = 0u; edge < 3u; edge++) {
106
+ let p = corners[edge];
107
+ let along = corners[(edge + 1u) % 3u] - p;
108
+ let t = clamp(dot(point - p, along) / max(dot(along, along), 1e-30), 0.0, 1.0);
109
+ let gap = length(point - (p + t * along));
110
+ if (gap < nearest) {
111
+ nearest = gap;
112
+ line = WaterOutlineLine(p, normalize(vec2<f32>(along.y, -along.x)));
113
+ }
114
+ }
115
+ return line;
116
+ }
117
+
118
+ // The particle's mirror image in a line of the outline: its front's centre and its direction mirrored. Not yet reflected.
119
+ fn water_particle_mirrored(particle: ${WATER_PARTICLE_STRUCT.wgsl_ref}, line: WaterOutlineLine) -> ${WATER_PARTICLE_STRUCT.wgsl_ref} {
120
+ var image = particle;
121
+ let direction = water_particle_direction(particle.angle);
122
+ let mirrored = direction - 2.0 * dot(direction, line.normal) * line.normal;
123
+ image.origin -= 2.0 * dot(particle.origin - line.point, line.normal) * line.normal;
124
+ image.angle = atan2(mirrored.y, mirrored.x);
125
+ image.reflected = 0u;
126
+ return image;
127
+ }
128
+
129
+ // Advance a particle by dt. scale turns the body's metric frame into its local one; reflection is the
130
+ // outline's amplitude reflection coefficient; threshold is the steepness |a|/r below which it dies; hint is what is
131
+ // already known of its leading arc.
132
+ fn water_particle_advance(input: ${WATER_PARTICLE_STRUCT.wgsl_ref}, dt: f32, geometry_index: u32, scale: vec2<f32>,
133
+ reflection: f32, threshold: f32, hint: WaterParticleArcHint) -> WaterParticleStep {
134
+ var particle = input;
135
+ let distance_before = water_particle_distance(particle);
136
+ let half_length_before = water_particle_half_length(particle);
137
+ particle.age += dt;
138
+ let distance_after = water_particle_distance(particle);
139
+ // energy spread over the widening circumference and the lengthening envelope (Jeschke & Wojtan 2017 eq. 17), and the
140
+ // water's own damping
141
+ particle.amplitude *= sqrt(max(distance_before, 1e-30) / max(distance_after, 1e-30)
142
+ * half_length_before / water_particle_half_length(particle)) * exp(-water_particle_damping(particle.radius) * dt);
143
+ // below the threshold a packet fades out rather than vanishing: its amplitude decays on top of the water's own
144
+ // damping until it is a tenth of the threshold's height, where it dies
145
+ let floor = threshold * particle.radius;
146
+ if (!(abs(particle.amplitude) >= floor)) {
147
+ particle.amplitude *= exp(-dt / WATER_PARTICLE_FADE_SECONDS);
148
+ if (!(abs(particle.amplitude) >= 0.1 * floor)) { return WaterParticleStep(particle, particle, 0u); }
149
+ }
150
+ // its support: its envelope's half-length either side of its front, its window's angle either side of its axis
151
+ let reach = water_particle_half_length(particle);
152
+ // whether any of it may still be over the body
153
+ var remains = true;
154
+ var image = particle;
155
+ var mirrored = false;
156
+ if (particle.reflected == 0u) {
157
+ // which of its leading arc's tested points are over the body: what the hint knows, then the axis's by a down-ray,
158
+ // the ends by the triangle under it, which covers them away from the outline, and the rest by a down-ray each
159
+ let ahead = distance_after + reach;
160
+ var known = hint.known;
161
+ var over = hint.over & known;
162
+ var triangle = hint.triangle;
163
+ if ((known & 1u) == 0u) {
164
+ let hit = water_particle_over_body(geometry_index, water_particle_support_point(particle, 0u, ahead) / scale);
165
+ known |= 1u;
166
+ over |= select(0u, 1u, hit.t >= 0.0);
167
+ triangle = hit.triangle;
168
+ }
169
+ if ((over & 1u) != 0u && (known & 6u) != 6u) {
170
+ var a: vec3<f32>;
171
+ var b: vec3<f32>;
172
+ var c: vec3<f32>;
173
+ geometry_read_triangle_positions(&a, &b, &c, geometries[geometry_index], triangle);
174
+ for (var k = 1u; k < 3u; k++) {
175
+ if (((known >> k) & 1u) == 0u && water_triangle_covers(a.xz, b.xz, c.xz, water_particle_support_point(particle, k, ahead) / scale)) {
176
+ known |= 1u << k;
177
+ over |= 1u << k;
178
+ }
179
+ }
180
+ }
181
+ for (var k = 1u; k < 3u; k++) {
182
+ if (((known >> k) & 1u) == 0u
183
+ && water_particle_over_body(geometry_index, water_particle_support_point(particle, k, ahead) / scale).t >= 0.0) { over |= 1u << k; }
184
+ }
185
+ // the first of them to leave the body: one off it whose radius was over it where its trailing arc was when the
186
+ // step began. With none over it there, the point is not leaving the body but entering it, as a mirror image's
187
+ // do: every radius of one starts beyond its outline.
188
+ var crossing = 3u;
189
+ var back = vec2<f32>(0.0);
190
+ var last: ${RAY_HIT_INFO.wgsl_ref};
191
+ for (var k = 0u; k < 3u && crossing == 3u; k++) {
192
+ if (((over >> k) & 1u) != 0u) { continue; }
193
+ back = water_particle_support_point(particle, k, distance_before - reach);
194
+ last = water_particle_over_body(geometry_index, back / scale);
195
+ if (last.t >= 0.0) { crossing = k; }
196
+ }
197
+ if (crossing < 3u) {
198
+ // it is kept this step: if all of it has left the body too, it dies at the next, unseen beyond the outline
199
+ particle.reflected = 1u;
200
+ // where from there that radius leaves the body
201
+ let leading = water_particle_support_point(particle, crossing, ahead);
202
+ var lo = 0.0;
203
+ var hi = 1.0;
204
+ for (var halving = 0u; halving < 10u; halving++) {
205
+ let mid = 0.5 * (lo + hi);
206
+ let probe = water_particle_over_body(geometry_index, mix(back, leading, mid) / scale);
207
+ if (probe.t >= 0.0) { lo = mid; last = probe; } else { hi = mid; }
208
+ }
209
+ // the mirror image of its front in the outline's own line, wherever that was crossed
210
+ image = water_particle_mirrored(particle, water_outline_line(geometry_index, last.triangle, mix(back, leading, lo), scale));
211
+ image.amplitude *= reflection;
212
+ mirrored = abs(image.amplitude) >= 0.1 * floor;
213
+ } else if (over == 0u) {
214
+ // with none of them over the body and none leaving it, all of it is beyond the outline: a splash off the
215
+ // mesh, or a mirror image landing off it at a corner (one entering the body has the point it was mirrored
216
+ // from over it)
217
+ remains = false;
218
+ }
219
+ } else {
220
+ remains = water_particle_arc_over(particle, geometry_index, scale, distance_after - reach);
221
+ }
222
+ // Yuksel's subdivision, at a coarser spacing: the three windows of a third of the angle sum to the front's height
223
+ // as the parents' did, so the surface does not change. A window splits once its arc along the front is longer than
224
+ // its envelope is across it, so a packet's support stays about round, whatever its stretch. An image is as wide as
225
+ // its packet and splits with it.
226
+ let split = select(1u, 3u, water_particle_width(particle) > water_particle_half_length(particle));
227
+ // a reflected packet lives until the last of it has left the body
228
+ if (!remains) { return WaterParticleStep(particle, particle, 0u); }
229
+ if (mirrored) { return WaterParticleStep(particle, image, 2u * split); }
230
+ return WaterParticleStep(particle, particle, split);
231
+ }
232
+
233
+ // The death threshold: a packet flatter than the body's own wind waves is not drawn, and the fuller the pool,
234
+ // the steeper a packet must be to stay.
235
+ fn water_particle_threshold(slope_variance: f32, live: u32, capacity: u32) -> f32 {
236
+ let pressure = f32(live) / f32(max(capacity, 1u));
237
+ return max(0.003, 0.1 * sqrt(max(slope_variance, 0.0))) / max(1.0 - pressure, 0.05);
238
+ }
239
+ `, [chunk_water_particle, chunk_ray_query_blas_nearest, chunk_geometry_read_triangle_positions]);