@woosh/meep-engine 3.41.0 → 3.42.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 (344) 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 +1 -1
  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/water_refraction/README.md +10 -11
  189. package/src/shade/playground/water_refraction/main.js +9 -8
  190. package/src/shade/playground/water_refraction/world.js +1 -1
  191. package/src/shade/playground/water_surface/README.md +43 -0
  192. package/src/shade/playground/water_surface/index.html +30 -0
  193. package/src/shade/playground/water_surface/main.d.ts +2 -0
  194. package/src/shade/playground/water_surface/main.d.ts.map +1 -0
  195. package/src/shade/playground/water_surface/main.js +154 -0
  196. package/src/shade/playground/water_surface/world.d.ts +44 -0
  197. package/src/shade/playground/water_surface/world.d.ts.map +1 -0
  198. package/src/shade/playground/water_surface/world.js +160 -0
  199. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  200. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +5 -0
  201. package/src/shade/renderer/binding/BufferBinding.js +2 -2
  202. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts.map +1 -1
  203. package/src/shade/renderer/buffer/table/GPUTypedTable.js +5 -3
  204. package/src/shade/renderer/buffer/table/GPUTypedTableDescriptor.d.ts +10 -3
  205. package/src/shade/renderer/buffer/table/GPUTypedTableDescriptor.d.ts.map +1 -1
  206. package/src/shade/renderer/buffer/table/GPUTypedTableDescriptor.js +17 -9
  207. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts +3 -0
  208. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts.map +1 -1
  209. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.js +16 -0
  210. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts +2 -0
  211. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts.map +1 -1
  212. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.js +11 -0
  213. package/src/shade/renderer/geometry/meshlet/build/meshoptimizer/geometry_to_meshlets_meshoptimizer.d.ts +1 -1
  214. package/src/shade/renderer/geometry/meshlet/build/meshoptimizer/geometry_to_meshlets_meshoptimizer.d.ts.map +1 -1
  215. package/src/shade/renderer/geometry/meshlet/build/meshoptimizer/geometry_to_meshlets_meshoptimizer.js +9 -3
  216. package/src/shade/renderer/geometry/util/geometry_simplify_redundant_topology.d.ts.map +1 -1
  217. package/src/shade/renderer/geometry/util/geometry_simplify_redundant_topology.js +2 -2
  218. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
  219. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +85 -0
  220. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -1
  221. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +12 -6
  222. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.d.ts.map +1 -1
  223. package/src/shade/renderer/geometry/virtual/runtime/VGeoPageFetcher.js +7 -0
  224. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts.map +1 -1
  225. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.js +3 -1
  226. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  227. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.js +2 -1
  228. package/src/shade/renderer/shader/chunk/math/fft/chunk_fft128_inverse.d.ts +13 -0
  229. package/src/shade/renderer/shader/chunk/math/fft/chunk_fft128_inverse.d.ts.map +1 -0
  230. package/src/shade/renderer/shader/chunk/math/fft/chunk_fft128_inverse.js +42 -0
  231. package/src/shade/renderer/shader/chunk/math/fft/chunk_fft128x4_inverse_workgroup.d.ts +15 -0
  232. package/src/shade/renderer/shader/chunk/math/fft/chunk_fft128x4_inverse_workgroup.d.ts.map +1 -0
  233. package/src/shade/renderer/shader/chunk/math/fft/chunk_fft128x4_inverse_workgroup.js +39 -0
  234. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
  235. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +2 -0
  236. package/src/shade/renderer/water/GPUWaterRenderer.d.ts +15 -0
  237. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  238. package/src/shade/renderer/water/GPUWaterRenderer.js +110 -30
  239. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +16 -8
  240. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +1 -1
  241. package/src/shade/renderer/water/medium/GPUWaterBodies.js +31 -26
  242. package/src/shade/renderer/water/medium/shader_water_meshlets.d.ts +0 -1
  243. package/src/shade/renderer/water/medium/shader_water_meshlets.d.ts.map +1 -1
  244. package/src/shade/renderer/water/medium/shader_water_meshlets.js +1 -39
  245. package/src/shade/renderer/water/shader_water.d.ts +0 -1
  246. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  247. package/src/shade/renderer/water/shader_water.js +201 -72
  248. package/src/shade/renderer/water/surface/GPUWaterSurface.d.ts +70 -0
  249. package/src/shade/renderer/water/surface/GPUWaterSurface.d.ts.map +1 -0
  250. package/src/shade/renderer/water/surface/GPUWaterSurface.js +199 -0
  251. package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.d.ts +5 -2
  252. package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.d.ts.map +1 -1
  253. package/src/shade/renderer/water/surface/WATER_WAVE_RECORD_STRUCT.js +32 -12
  254. package/src/shade/renderer/water/surface/chunk_water_surface_sample.d.ts +22 -0
  255. package/src/shade/renderer/water/surface/chunk_water_surface_sample.d.ts.map +1 -0
  256. package/src/shade/renderer/water/surface/chunk_water_surface_sample.js +217 -0
  257. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +65 -11
  258. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts.map +1 -1
  259. package/src/shade/renderer/water/surface/graph_water_tessellation.js +163 -28
  260. package/src/shade/renderer/water/surface/lod/WATER_LOD.d.ts +51 -0
  261. package/src/shade/renderer/water/surface/lod/WATER_LOD.d.ts.map +1 -0
  262. package/src/shade/renderer/water/surface/lod/WATER_LOD.js +95 -0
  263. package/src/shade/renderer/water/surface/lod/chunk_water_lod.d.ts +10 -0
  264. package/src/shade/renderer/water/surface/lod/chunk_water_lod.d.ts.map +1 -0
  265. package/src/shade/renderer/water/surface/lod/chunk_water_lod.js +127 -0
  266. package/src/shade/renderer/water/surface/lod/chunk_water_lod_cell.d.ts +17 -0
  267. package/src/shade/renderer/water/surface/lod/chunk_water_lod_cell.d.ts.map +1 -0
  268. package/src/shade/renderer/water/surface/lod/chunk_water_lod_cell.js +246 -0
  269. package/src/shade/renderer/water/surface/lod/shader_water_lod.d.ts +118 -0
  270. package/src/shade/renderer/water/surface/lod/shader_water_lod.d.ts.map +1 -0
  271. package/src/shade/renderer/water/surface/lod/shader_water_lod.js +727 -0
  272. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.d.ts +60 -0
  273. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.d.ts.map +1 -0
  274. package/src/shade/renderer/water/surface/particles/GPUWaterParticles.js +228 -0
  275. package/src/shade/renderer/water/surface/particles/WATER_PARTICLE_STRUCT.d.ts +17 -0
  276. package/src/shade/renderer/water/surface/particles/WATER_PARTICLE_STRUCT.d.ts.map +1 -0
  277. package/src/shade/renderer/water/surface/particles/WATER_PARTICLE_STRUCT.js +49 -0
  278. package/src/shade/renderer/water/surface/particles/chunk_water_particle.d.ts +22 -0
  279. package/src/shade/renderer/water/surface/particles/chunk_water_particle.d.ts.map +1 -0
  280. package/src/shade/renderer/water/surface/particles/chunk_water_particle.js +143 -0
  281. package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.d.ts +15 -0
  282. package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.d.ts.map +1 -0
  283. package/src/shade/renderer/water/surface/particles/chunk_water_particle_step.js +121 -0
  284. package/src/shade/renderer/water/surface/particles/shader_water_particles.d.ts +83 -0
  285. package/src/shade/renderer/water/surface/particles/shader_water_particles.d.ts.map +1 -0
  286. package/src/shade/renderer/water/surface/particles/shader_water_particles.js +502 -0
  287. package/src/shade/renderer/water/surface/shader_water_cull.d.ts +42 -0
  288. package/src/shade/renderer/water/surface/shader_water_cull.d.ts.map +1 -0
  289. package/src/shade/renderer/water/surface/shader_water_cull.js +269 -0
  290. package/src/shade/renderer/water/surface/shader_water_waves_combine.d.ts +15 -0
  291. package/src/shade/renderer/water/surface/shader_water_waves_combine.d.ts.map +1 -0
  292. package/src/shade/renderer/water/surface/shader_water_waves_combine.js +73 -0
  293. package/src/shade/renderer/water/surface/shader_water_waves_derive.d.ts +11 -0
  294. package/src/shade/renderer/water/surface/shader_water_waves_derive.d.ts.map +1 -0
  295. package/src/shade/renderer/water/surface/shader_water_waves_derive.js +78 -0
  296. package/src/shade/renderer/water/surface/spectrum/GPUWaterSpectrum.d.ts +35 -0
  297. package/src/shade/renderer/water/surface/spectrum/GPUWaterSpectrum.d.ts.map +1 -0
  298. package/src/shade/renderer/water/surface/spectrum/GPUWaterSpectrum.js +103 -0
  299. package/src/shade/renderer/water/surface/spectrum/WATER_BAND_STATE.d.ts +22 -0
  300. package/src/shade/renderer/water/surface/spectrum/WATER_BAND_STATE.d.ts.map +1 -0
  301. package/src/shade/renderer/water/surface/spectrum/WATER_BAND_STATE.js +57 -0
  302. package/src/shade/renderer/water/surface/spectrum/WATER_SPECTRUM.d.ts +22 -0
  303. package/src/shade/renderer/water/surface/spectrum/WATER_SPECTRUM.d.ts.map +1 -0
  304. package/src/shade/renderer/water/surface/spectrum/WATER_SPECTRUM.js +25 -0
  305. package/src/shade/renderer/water/surface/spectrum/chunk_water_jonswap.d.ts +14 -0
  306. package/src/shade/renderer/water/surface/spectrum/chunk_water_jonswap.d.ts.map +1 -0
  307. package/src/shade/renderer/water/surface/spectrum/chunk_water_jonswap.js +48 -0
  308. package/src/shade/renderer/water/surface/spectrum/chunk_water_spectrum.d.ts +23 -0
  309. package/src/shade/renderer/water/surface/spectrum/chunk_water_spectrum.d.ts.map +1 -0
  310. package/src/shade/renderer/water/surface/spectrum/chunk_water_spectrum.js +169 -0
  311. package/src/shade/renderer/water/surface/spectrum/shader_water_spectrum.d.ts +26 -0
  312. package/src/shade/renderer/water/surface/spectrum/shader_water_spectrum.d.ts.map +1 -0
  313. package/src/shade/renderer/water/surface/spectrum/shader_water_spectrum.js +161 -0
  314. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.d.ts.map +1 -1
  315. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +18 -6
  316. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  317. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +11 -3
  318. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.d.ts +0 -28
  319. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.d.ts.map +0 -1
  320. package/src/core/geom/2d/polygon/polygon2_triangulate.corpus.js +0 -86
  321. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.d.ts +0 -29
  322. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.d.ts.map +0 -1
  323. package/src/engine/ecs/storage/binary/object-v2/serializerTestHarness.js +0 -44
  324. package/src/shade/renderer/water/medium/shader_water_bodies_derive.d.ts +0 -4
  325. package/src/shade/renderer/water/medium/shader_water_bodies_derive.d.ts.map +0 -1
  326. package/src/shade/renderer/water/medium/shader_water_bodies_derive.js +0 -32
  327. package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.d.ts +0 -25
  328. package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.d.ts.map +0 -1
  329. package/src/shade/renderer/water/surface/GPUWaterWaveSimulation.js +0 -128
  330. package/src/shade/renderer/water/surface/chunk_water_tessellation.d.ts +0 -9
  331. package/src/shade/renderer/water/surface/chunk_water_tessellation.d.ts.map +0 -1
  332. package/src/shade/renderer/water/surface/chunk_water_tessellation.js +0 -144
  333. package/src/shade/renderer/water/surface/chunk_water_wave.d.ts +0 -13
  334. package/src/shade/renderer/water/surface/chunk_water_wave.d.ts.map +0 -1
  335. package/src/shade/renderer/water/surface/chunk_water_wave.js +0 -40
  336. package/src/shade/renderer/water/surface/shader_water_tiles.d.ts +0 -4
  337. package/src/shade/renderer/water/surface/shader_water_tiles.d.ts.map +0 -1
  338. package/src/shade/renderer/water/surface/shader_water_tiles.js +0 -123
  339. package/src/shade/renderer/water/surface/shader_water_wave_batch.d.ts +0 -6
  340. package/src/shade/renderer/water/surface/shader_water_wave_batch.d.ts.map +0 -1
  341. package/src/shade/renderer/water/surface/shader_water_wave_batch.js +0 -85
  342. package/src/shade/renderer/water/surface/shader_water_wave_domain.d.ts +0 -6
  343. package/src/shade/renderer/water/surface/shader_water_wave_domain.d.ts.map +0 -1
  344. package/src/shade/renderer/water/surface/shader_water_wave_domain.js +0 -83
@@ -38,10 +38,8 @@ export class SoftwareGPUDevice extends SoftwareGPUObjectBase implements GPUDevic
38
38
  * @param {GPUFeatureName[]} [descriptor.requiredFeatures] optional features to enable, from
39
39
  * {@link SUPPORTED_OPTIONAL_FEATURES}. Asking for one this device cannot emulate throws, as
40
40
  * `requestDevice` rejects for one the adapter does not have.
41
- * @param {Partial<GPUSupportedLimits>} [descriptor.requiredLimits] limits to report instead of
42
- * the defaults. Only *worse* values are accepted — see {@link build_limits}. Lowering one is how
43
- * a test reaches the clamping paths the renderer takes on a small device without allocating
44
- * anything large.
41
+ * @param {Partial<GPUSupportedLimits>} [descriptor.requiredLimits] requested limits; worse-than-default
42
+ * requests preserve the defaults, and unsupported better requests are refused
45
43
  */
46
44
  constructor(descriptor?: {
47
45
  label?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"SoftwareGPUDevice.d.ts","sourceRoot":"","sources":["../../../../../src/shade/device/mock/SoftwareGPUDevice.js"],"names":[],"mappings":"AAsQA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wEAFgB,SAAS;IAkCrB;;;;;;;;;;OAUG;IACH;QAT+B,KAAK,GAAzB,MAAM;QACwB,gBAAgB,GAA9C,gBAAgB;QAGyB,cAAc,GAAvD,2BAA2B;OAyBrC;IAzDD;;;;;OAKG;IACH,qCAEC;IAOD;;;;;;OAMG;IACH,iCAEC;IAmCD;;OAEG;IACH,kCAEC;IAID;;OAEG;IACH,sBAEC;IAaD;;;;;;;;OAQG;IACH,iEAUC;IAwBD;;;;;OAKG;IACH,uCAEC;IAID;;;;OAIG;IACH,2BAEC;IAED;;;;;;;OAOG;IACH,gBAcC;IAID;;;;;;;;;OASG;IACH,uBALW,MAAM,YACN,kCAAkC,YAClC,OAAO,GAAC,uBAAuB,GAC7B,IAAI,CAIhB;IAED;;;;;OAKG;IACH,0BALW,MAAM,YACN,kCAAkC,YAClC,OAAO,GAAC,oBAAoB,GAC1B,IAAI,CAIhB;IAED;;;OAGG;IACH,qBAHW,KAAK,GACH,OAAO,CAInB;IASD;;;;;;;OAOG;IACH,wCAFa,IAAI,CAUhB;IAED;;;;;;;;;OASG;IACH,iBAHa,QAAQ,mBAAiB,IAAI,CAAC,CAc1C;IAED;;;;;;;;;;;;;;OAcG;IACH,yCAFa,IAAI,CA4BhB;IAED;;;;;;;;;OASG;IACH,yDAcC;IAmJD;;;;;;OAMG;IACH,4DAcC;IAED;;;;;;OAMG;IACH,6DAEC;IAED;;;OAGG;IACH,oFAEC;IAED;;;;;;;OAOG;IACH,kEAUC;IAkCD;;;OAGG;IACH,iFAcC;IAED;;;;;;;OAOG;IACH,2EAEC;IAED;;;;;;OAMG;IACH,iFAEC;IAED;;;;;OAKG;IACH,oFAEC;IAUD;;;;;OAKG;IACH,kBAFa,MAAM,CAMlB;IAED;;;OAGG;IACH,+DAQC;IA4BD;;;OAGG;IACH,kFAEC;IAGL;;;OAGG;IACH,8BAFU,OAAO,CAE8B;;CAN9C;;;;;;;;;;;;WA/sBa,mBAAiB,IAAI;;sCArQG,4BAA4B;kCAHhC,wBAAwB;mCASvB,yBAAyB"}
1
+ {"version":3,"file":"SoftwareGPUDevice.d.ts","sourceRoot":"","sources":["../../../../../src/shade/device/mock/SoftwareGPUDevice.js"],"names":[],"mappings":"AA+QA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wEAFgB,SAAS;IAkCrB;;;;;;;;OAQG;IACH;QAP+B,KAAK,GAAzB,MAAM;QACwB,gBAAgB,GAA9C,gBAAgB;QAGyB,cAAc,GAAvD,2BAA2B;OAuBrC;IAvDD;;;;;OAKG;IACH,qCAEC;IAOD;;;;;;OAMG;IACH,iCAEC;IAiCD;;OAEG;IACH,kCAEC;IAID;;OAEG;IACH,sBAEC;IAaD;;;;;;;;OAQG;IACH,iEAUC;IAwBD;;;;;OAKG;IACH,uCAEC;IAID;;;;OAIG;IACH,2BAEC;IAED;;;;;;;OAOG;IACH,gBAcC;IAID;;;;;;;;;OASG;IACH,uBALW,MAAM,YACN,kCAAkC,YAClC,OAAO,GAAC,uBAAuB,GAC7B,IAAI,CAIhB;IAED;;;;;OAKG;IACH,0BALW,MAAM,YACN,kCAAkC,YAClC,OAAO,GAAC,oBAAoB,GAC1B,IAAI,CAIhB;IAED;;;OAGG;IACH,qBAHW,KAAK,GACH,OAAO,CAInB;IASD;;;;;;;OAOG;IACH,wCAFa,IAAI,CAUhB;IAED;;;;;;;;;OASG;IACH,iBAHa,QAAQ,mBAAiB,IAAI,CAAC,CAc1C;IAED;;;;;;;;;;;;;;OAcG;IACH,yCAFa,IAAI,CA4BhB;IAED;;;;;;;;;OASG;IACH,yDAcC;IAmJD;;;;;;OAMG;IACH,4DAcC;IAED;;;;;;OAMG;IACH,6DAEC;IAED;;;OAGG;IACH,oFAEC;IAED;;;;;;;OAOG;IACH,kEAUC;IAkCD;;;OAGG;IACH,iFAcC;IAED;;;;;;;OAOG;IACH,2EAEC;IAED;;;;;;OAMG;IACH,iFAEC;IAED;;;;;OAKG;IACH,oFAEC;IAUD;;;;;OAKG;IACH,kBAFa,MAAM,CAMlB;IAED;;;OAGG;IACH,+DAQC;IA4BD;;;OAGG;IACH,kFAEC;IAGL;;;OAGG;IACH,8BAFU,OAAO,CAE8B;;CAN9C;;;;;;;;;;;;WA7sBa,mBAAiB,IAAI;;sCA9QG,4BAA4B;kCAHhC,wBAAwB;mCASvB,yBAAyB"}
@@ -87,11 +87,11 @@ const LIMIT_NAMES = Object.keys(DEFAULT_LIMITS);
87
87
  /**
88
88
  * Build the limits one device reports.
89
89
  *
90
- * An override may only make a limit *worse*, which is the direction `requestDevice` allows to
91
- * succeed: asking for a limit better than the adapter supports rejects there, and granting one here
92
- * would let a test pass against a device no hardware offers. "Better" is larger for a `max*` limit
93
- * and smaller for a `min*` one — the alignment limits are minimums, and a device that permitted a
94
- * *smaller* alignment would hide exactly the misalignment bugs those limits exist to catch.
90
+ * Like `requestDevice`, requests worse than the defaults leave those defaults in place.
91
+ * This software device supports the default capabilities, so a better request is refused.
92
+ * "Better" means larger for maximum limits and smaller for minimum alignment limits.
93
+ *
94
+ * @see https://gpuweb.github.io/gpuweb/#dom-gpuadapter-requestdevice
95
95
  *
96
96
  * @param {Partial<GPUSupportedLimits>} [overrides]
97
97
  * @returns {GPUSupportedLimits} frozen, as a real one is read-only
@@ -100,13 +100,23 @@ function build_limits(overrides = {}) {
100
100
  const limits = { ...DEFAULT_LIMITS };
101
101
 
102
102
  for (const [name, value] of Object.entries(overrides)) {
103
+ if (value === undefined) {
104
+ continue;
105
+ }
103
106
  if (!LIMIT_NAMES.includes(name)) {
104
- throw new TypeError(
105
- `SoftwareGPUDevice: '${name}' is not a GPUSupportedLimits member`
107
+ throw new DOMException(
108
+ `SoftwareGPUDevice: '${name}' is not a GPUSupportedLimits member`,
109
+ 'OperationError'
106
110
  );
107
111
  }
108
112
 
109
113
  const is_minimum = name.startsWith('min');
114
+ if (is_minimum && (!Number.isInteger(Math.log2(value)) || value >= 2 ** 32)) {
115
+ throw new DOMException(
116
+ `SoftwareGPUDevice: required alignment limit ${name}=${value} must be a power of two less than 2^32`,
117
+ 'OperationError'
118
+ );
119
+ }
110
120
  const better = is_minimum
111
121
  ? value < DEFAULT_LIMITS[name]
112
122
  : value > DEFAULT_LIMITS[name];
@@ -118,7 +128,6 @@ function build_limits(overrides = {}) {
118
128
  );
119
129
  }
120
130
 
121
- limits[name] = value;
122
131
  }
123
132
 
124
133
  return Object.freeze(limits);
@@ -332,10 +341,8 @@ export class SoftwareGPUDevice extends SoftwareGPUObjectBase {
332
341
  * @param {GPUFeatureName[]} [descriptor.requiredFeatures] optional features to enable, from
333
342
  * {@link SUPPORTED_OPTIONAL_FEATURES}. Asking for one this device cannot emulate throws, as
334
343
  * `requestDevice` rejects for one the adapter does not have.
335
- * @param {Partial<GPUSupportedLimits>} [descriptor.requiredLimits] limits to report instead of
336
- * the defaults. Only *worse* values are accepted — see {@link build_limits}. Lowering one is how
337
- * a test reaches the clamping paths the renderer takes on a small device without allocating
338
- * anything large.
344
+ * @param {Partial<GPUSupportedLimits>} [descriptor.requiredLimits] requested limits; worse-than-default
345
+ * requests preserve the defaults, and unsupported better requests are refused
339
346
  */
340
347
  constructor(descriptor = {}) {
341
348
  super(descriptor);
@@ -990,4 +997,4 @@ export class SoftwareGPUDevice extends SoftwareGPUObjectBase {
990
997
  * @readonly
991
998
  * @type {boolean}
992
999
  */
993
- SoftwareGPUDevice.prototype.isSoftwareGPUDevice = true;
1000
+ SoftwareGPUDevice.prototype.isSoftwareGPUDevice = true;
@@ -1 +1 @@
1
- {"version":3,"file":"sweep_views.d.ts","sourceRoot":"","sources":["../../../../../src/shade/playground/skinned_blas_refit/sweep_views.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;;GAYG;AACH;IAX6B,QAAQ;IACC,MAAM;IAClB,KAAK;IACJ,MAAM,EAAtB,MAAM;IAC4B,OAAO,UAAhC,OAAO,KAAG,IAAI;IACN,QAAQ,GAAzB,MAAM;IACa,UAAU,GAA7B,MAAM,EAAE;IACS,QAAQ,GAAzB,MAAM;IACW,OAAO,GAAxB,MAAM;IACJ,QAAQ,MAAM,CAAC,CAwG3B"}
1
+ {"version":3,"file":"sweep_views.d.ts","sourceRoot":"","sources":["../../../../../src/shade/playground/skinned_blas_refit/sweep_views.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;;;GAYG;AACH;IAX6B,QAAQ;IACC,MAAM;IAClB,KAAK;IACJ,MAAM,EAAtB,MAAM;IAC4B,OAAO,UAAhC,OAAO,KAAG,IAAI;IACN,QAAQ,GAAzB,MAAM;IACa,UAAU,GAA7B,MAAM,EAAE;IACS,QAAQ,GAAzB,MAAM;IACW,OAAO,GAAxB,MAAM;IACJ,QAAQ,MAAM,CAAC,CAyG3B"}
@@ -61,6 +61,7 @@ export async function sweep_views({
61
61
 
62
62
  const kept = {
63
63
  position: [...camera.transform.translation],
64
+ rotation: [...camera.transform.rotation],
64
65
  near: camera.near,
65
66
  far: camera.far,
66
67
  };
@@ -108,7 +109,7 @@ export async function sweep_views({
108
109
  }
109
110
 
110
111
  camera.transform.setTranslation(...kept.position);
111
- camera.transform.lookAt(centre);
112
+ camera.transform.setRotation(...kept.rotation);
112
113
  camera.near = kept.near;
113
114
  camera.far = kept.far;
114
115
 
@@ -23,14 +23,12 @@ below-interface view. The grazing camera stays over the submerged floor.
23
23
 
24
24
  Water is an entity with `Water`, `MeshletGeometry` and `Transform64`. The mesh authors the outline
25
25
  and elevations, and the transform places it; Level edits the transform's height. This fixture
26
- has a curved, coarse authored outline. Optical controls edit Water. Optional WaterWaves supplies wind
27
- forcing to a persistent shared GPU displacement atlas, with 128² samples per active body. The existing
28
- geometry BLAS bakes the authored footprint into a simulation mask when a wave row is created;
29
- dry samples remain zero, including holes and gaps. Vertices sample the field in local xz and move
30
- along local y. This primitive simulation therefore expects a surface that can be represented as a
31
- height field in local xz; multiple stacked surfaces sharing that domain also share its displacement.
32
- Calm meshes allocate no grid. The simulation uses a one-metre reference depth and
33
- does not infer bathymetry from the mesh. Screen reflections can be disabled while retaining the
26
+ has a curved, coarse authored outline. Optical controls edit Water. Optional WaterWaves sets the wind:
27
+ the body's waves are a fetch-limited JONSWAP sea over its own extent along the wind, drawn from 18
28
+ spectral bands every body shares, plus the wave particles of its splashes, which reflect off the mesh's
29
+ outline (`WATER_SURFACE_SIMULATION_PLAN_2026_10_06.md`). Vertices sample both in the body's metric local
30
+ frame and move in it; deep water is assumed, and nothing is inferred from bathymetry. A body with a
31
+ triangle too steep to flatten onto a reference plane stays calm. Screen reflections can be disabled while retaining the
34
32
  fallback to the renderer's indirect lighting (IBL, or Brick4 when it is the active mode).
35
33
  The Newton, bounded HZB traversal, and undisplaced control modes all use the same AVBOIT path.
36
34
  The Medium select picks one of the water presets (`shade/renderer/medium/water/water_presets.js`):
@@ -162,8 +160,8 @@ tiny-loss resolve guard; existing particle, mesh and ribbon APIs remain intact.
162
160
  Water bodies occupy persistent rows in the existing scene database. Optical and component edits
163
161
  queue CPU writes; idle updates do not enumerate bodies. GPU page iteration, the existing prefix
164
162
  scan, ordered meshlet expansion and indirect draws cover the scene. A GPU reduction supplies signed
165
- local-y displacement bounds after each simulation update. Body frustum culling expands the authored
166
- bounds by those extrema before applying the GPU world transform.
163
+ local-y and horizontal displacement bounds every frame. Body frustum culling expands the authored
164
+ bounds by them before applying the GPU world transform.
167
165
 
168
166
  Following Far Cry 5's view-tile approach, each candidate triangle classifies its swept footprint into
169
167
  view tiles. A tile contains 16×16 cells; `settings.tessellation_pixels` sets their reference-view spacing
@@ -181,7 +179,8 @@ against the view planes. Calm bodies project the authored triangles directly. Re
181
179
  when displacement can bring them into view. Opaque depth is tested after displacement, so an
182
180
  undisplaced depth rejection cannot hide a crest. Both surface passes share the same patch counts
183
181
  and reconstruction inputs. Simulation is independent of camera position and render resolution;
184
- wave dispatch count depends on fixed steps, not the number of bodies. Device buffer and indirect
182
+ the spectral bands cost the same for any number of bodies, and particles are dispatched from their
183
+ GPU count. Device buffer and indirect
185
184
  draw limits still bound scene complexity. If the reference is coplanar with the camera, it moves
186
185
  farther beyond the displacement envelope to retain a projectable surface. The body's conservative
187
186
  swept span sets one shared grid spacing, at least the requested pixel spacing. This bounds each
@@ -25,11 +25,12 @@ import { ParticipatingMediaVolume } from "../../renderer/volumetrics/Participati
25
25
  import { water_medium_preset } from "../../renderer/medium/water/water_presets.js";
26
26
  import { water_finalize_shader_brick4, water_finalize_shader_ibl, water_shader } from "../../renderer/water/shader_water.js";
27
27
  import * as water_shaders from "../../renderer/water/shader_water_avboit.js";
28
- import { shader_water_bodies_derive } from "../../renderer/water/medium/shader_water_bodies_derive.js";
29
- import { shader_water_meshlet_counts, shader_water_meshlets_expand } from "../../renderer/water/medium/shader_water_meshlets.js";
30
- import { shader_water_wave_batch, shader_water_wave_batch_finish } from "../../renderer/water/surface/shader_water_wave_batch.js";
31
- import { shader_water_wave_domain, shader_water_wave_bounds } from "../../renderer/water/surface/shader_water_wave_domain.js";
32
- import { shader_water_tiles } from "../../renderer/water/surface/shader_water_tiles.js";
28
+ import { shader_water_meshlets_expand } from "../../renderer/water/medium/shader_water_meshlets.js";
29
+ import * as spectrum_shaders from "../../renderer/water/surface/spectrum/shader_water_spectrum.js";
30
+ import * as particle_shaders from "../../renderer/water/surface/particles/shader_water_particles.js";
31
+ import * as cull_shaders from "../../renderer/water/surface/shader_water_cull.js";
32
+ import * as lod_shaders from "../../renderer/water/surface/lod/shader_water_lod.js";
33
+ import { shader_water_waves_combine } from "../../renderer/water/surface/shader_water_waves_combine.js";
33
34
  import { install_profile_hotkey } from "../profile_hotkey.js";
34
35
  import { build_world } from "./world.js";
35
36
 
@@ -164,9 +165,9 @@ async function main() {
164
165
  if(!ready)return;
165
166
  const device=graphics.renderer.graphics.device,errors=[];
166
167
  for(const shader of [water_shader,water_finalize_shader_ibl,water_finalize_shader_brick4,
167
- ...[shader_water_bodies_derive,shader_water_meshlet_counts,shader_water_meshlets_expand,
168
- shader_water_wave_batch,shader_water_wave_batch_finish,shader_water_wave_domain,shader_water_wave_bounds,
169
- shader_water_tiles,...Object.values(water_shaders)].map(s=>s.descriptor)]){
168
+ ...[shader_water_meshlets_expand,shader_water_waves_combine,...Object.values(spectrum_shaders),
169
+ ...Object.values(particle_shaders),...Object.values(cull_shaders),...Object.values(lod_shaders),
170
+ ...Object.values(water_shaders)].map(s=>s?.descriptor)]){
170
171
  if(typeof shader?.source!=="string")continue;
171
172
  const module=device.createShaderModule({code:shader.source});const info=await module.getCompilationInfo();
172
173
  errors.push(...info.messages.filter(m=>m.type==="error").map(m=>`${m.lineNum}: ${m.message}`));
@@ -93,7 +93,7 @@ export async function build_world(dataset) {
93
93
  water_normals[i]=0;water_normals[i+1]=1;water_normals[i+2]=0;
94
94
  }
95
95
  const water_geometry=meshlets(water_plane),water_transform=pose(16,0,16);
96
- // the primitive wave simulation's forcing; the overlapping second body below has none and stays calm
96
+ // the wind that raises its waves; the overlapping second body below has none and stays calm
97
97
  const waves=new WaterWaves();
98
98
  const water_entity=build(new Entity().add(water).add(waves).add(water_geometry).add(water_transform));
99
99
  const add_mesh=(geo,m,x,y,z,rotation)=>{
@@ -0,0 +1,43 @@
1
+ # Water / surface
2
+
3
+ One scene, four bodies of water, from a cup to an ocean: the surface simulation of
4
+ `WATER_SURFACE_SIMULATION_PLAN_2026_10_06.md` at every scale it has to work at.
5
+
6
+ | Stop | Body | Mesh | Wind | What to look for |
7
+ |---|---|---|---|---|
8
+ | Cup | 4 cm of tea on a table | a 32-segment disk | 2 m/s | centimetre ripples at most; a click rings the cup and the wall sends it back |
9
+ | Puddle | 2 m across, 1 cm deep | a wobbly disk | 4 m/s | rain (the checkbox) is the point here: rings of a few millimetres that die within a second |
10
+ | Lake | 120 × 60 m in a basin | its outline only | 6 m/s | short wind waves over the checkered bed; splashes reflect off the shore at 0.3 |
11
+ | Ocean | 5 km disk round an island hole | an annulus | 10 m/s, 200 km of sea upwind | swell; the island's outline reflects particles |
12
+
13
+ Every body is an ordinary entity: `Water` + `WaterWaves` + `MeshletGeometry` + `Transform64`. The meshes
14
+ author outlines; the surface's detail comes from the waves. Nothing in the scene is specific to its scale: the
15
+ wind and the fetch set each body's spectrum (fetch-limited JONSWAP over the body's extent along the wind,
16
+ plus `upwindFetch`), and all four share the same 18 spectral bands and one wave-particle pool.
17
+
18
+ ## Controls
19
+
20
+ - **Scale** buttons move the camera and set its near and far planes for the stop.
21
+ - **Wind ×** scales every body's own wind speed; **Direction** turns all of them. A change of direction
22
+ turns the waves over four seconds.
23
+ - **Click** the water to splash it, with a radius suited to the stop and the **Kick** speed. **Rain** drops
24
+ splashes on the current stop's body at the chosen rate.
25
+ - **Measure GPU** records 2.5 s of frames and lists the surface passes in µs per frame. **Profile (T)**
26
+ saves a full `.sgpt` capture.
27
+
28
+ ## What it shows and what it does not
29
+
30
+ The floors under the water are checkered so refraction shows the slopes without a sky. The page asks for the
31
+ default octahedral sky (`/test_assets/environments/octahedral/rustig_koppie_puresky_2k.hdr`); without it,
32
+ reflections show the procedural sky only, and the ocean, seen from above its deep water, reads dark and flat
33
+ except where it refracts the island's slope.
34
+
35
+ The ocean stop puts the camera 9 m above the sea; at the wind slider's top (20 m/s) the camera is among the waves.
36
+ The surface is cut from a distance-LOD lattice (`WATER_SURFACE_DISTANCE_LOD_PROPOSAL_2026_10_06.md`), so the waves
37
+ near the camera keep their cells however tall they are.
38
+
39
+ Measured on an RTX 4090, 1058 × 746 (headless Chrome, 2026-10-06), the ocean at 20 m/s from 9 m, with a fixed load
40
+ holding the GPU's clocks: culling 17 µs, band spectrum 30 µs (the bands the view can draw), bounds 7 µs, lattice passes
41
+ 232 µs and scans 61 µs for 2,820 patches, 176,000 interior and 146,000 boundary cells; the two surface passes 1.06 and
42
+ 1.50 ms, of which ~0.25 ms each shades the waves too short for the cells per pixel. Bodies out of view cost one culling thread each: 4,000 added under 2 µs. The GPU lowers its clocks on a light
43
+ frame, so time a pass against another setting in the same capture, or with a fixed load beside it.
@@ -0,0 +1,30 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Water · surface at every scale</title>
4
+ <style>
5
+ :root{color-scheme:dark;font:14px/1.45 system-ui,sans-serif;color:#d6e4ea;background:#10161b}*{box-sizing:border-box}
6
+ body{margin:0;display:grid;grid-template-columns:minmax(0,1fr) 320px;grid-template-rows:minmax(0,1fr);height:100vh;overflow:hidden}
7
+ #viewport{min-width:0;min-height:0;overflow:hidden;position:relative;outline:none}#viewport canvas{width:100%;height:100%}
8
+ aside{padding:20px;overflow:auto;border-left:1px solid #2d3a42;background:#151e25}h1{font-size:20px;margin:0 0 6px}h2{font-size:13px;color:#8cb9bf;text-transform:uppercase;letter-spacing:.07em;margin:22px 0 9px}
9
+ p{margin:8px 0;color:#9faeb9;font-size:12px}label{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:8px 0}
10
+ input[type=range]{width:130px}input,select,button{font:inherit;background:#202d36;border:1px solid #3c505e;border-radius:5px;color:#e2edf0;padding:5px}button{cursor:pointer}button:hover{background:#304753}
11
+ .row{display:flex;gap:6px;flex-wrap:wrap}pre{white-space:pre-wrap;overflow-wrap:anywhere;font:11px/1.5 monospace;color:#8bd3d5;background:#0c151b;padding:10px;border-radius:5px}
12
+ #status{border-left:3px solid #70b8b5;padding:10px;font-size:12px;background:#1d2c32}#badge{position:absolute;top:16px;left:16px;pointer-events:none;background:#13242cd9;padding:8px 12px;border-radius:5px;color:#c7eff0;font-size:12px}
13
+ </style></head>
14
+ <body tabindex="0"><div id="viewport" tabindex="0"><div id="badge">Drag to orbit · wheel to zoom · click the water to splash</div></div>
15
+ <aside><h1>Water / surface</h1><p>One spectrum and one particle pool for a cup, a puddle, a lake and an ocean.</p><div id="status">Starting renderer…</div>
16
+ <h2>Scale</h2>
17
+ <div class="row"><button class="stop" data-stop="cup">Cup</button><button class="stop" data-stop="puddle">Puddle</button><button class="stop" data-stop="lake">Lake</button><button class="stop" data-stop="ocean">Ocean</button><button class="stop" data-stop="aerial">Ocean, aerial</button></div>
18
+ <h2>Wind</h2>
19
+ <label>Wind × each body's own<input id="wind" type="range" min="0" max="2" step=".05" value="1"></label>
20
+ <label>Direction °<input id="direction" type="range" min="0" max="360" step="1" value="30"></label>
21
+ <pre id="winds"></pre>
22
+ <h2>Splashes</h2>
23
+ <label>Kick m/s<input id="kick" type="range" min="0.1" max="4" step=".1" value="1.5"></label>
24
+ <label>Rain on this body<input id="rain" type="checkbox"></label>
25
+ <label>Drops per second<input id="rate" type="range" min="1" max="200" step="1" value="40"></label>
26
+ <div class="row"><button id="pause">Pause</button><button id="measure">Measure GPU</button><button id="profile">Profile (T)</button></div>
27
+ <pre id="report">Measure records 2.5 s of frames and lists the surface passes, µs per frame.</pre>
28
+ </aside>
29
+ <script type="module" src="./main.js"></script>
30
+ </body></html>
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../src/shade/playground/water_surface/main.js"],"names":[],"mappings":""}
@@ -0,0 +1,154 @@
1
+ import Quaternion from "../../../core/geom/Quaternion.js";
2
+ import Vector3 from "../../../core/geom/Vector3.js";
3
+ import { m4_invert } from "../../../core/geom/3d/mat4/m4_invert.js";
4
+ import { EntityComponentDataset } from "../../../engine/ecs/EntityComponentDataset.js";
5
+ import { EntityManager } from "../../../engine/ecs/EntityManager.js";
6
+ import { Entity } from "../../../engine/ecs/Entity.js";
7
+ import { Transform64 } from "../../../engine/ecs/transform/Transform64.js";
8
+ import { Light } from "../../../engine/graphics/ecs/light/Light.js";
9
+ import { GraphicsEngine } from "../../../engine/graphics3/GraphicsEngine.js";
10
+ import { LightSystem } from "../../../engine/graphics3/LightSystem.js";
11
+ import { ShadedGeometrySystem } from "../../../engine/graphics3/ShadedGeometrySystem.js";
12
+ import { WaterSystem } from "../../../engine/graphics3/WaterSystem.js";
13
+ import { GPUProfileLevel } from "../../device/timing/profile/GPUProfileLevel.js";
14
+ import { GPUProfileSession } from "../../device/timing/profile/GPUProfileSession.js";
15
+ import { sgpt_read_capture } from "../../device/timing/profile/sgpt_read_capture.js";
16
+ import { OrbitalCameraController } from "../../renderer/camera/OrbitalCameraController.js";
17
+ import { create_frame_loop } from "../../renderer/create_frame_loop.js";
18
+ import { Scene } from "../../renderer/scene/Scene.js";
19
+ import { load_default_environment } from "../load_default_environment.js";
20
+ import { install_profile_hotkey } from "../profile_hotkey.js";
21
+ import { build_world } from "./world.js";
22
+
23
+ const element = id => document.getElementById(id);
24
+ const number = id => Number(element(id).value);
25
+
26
+ /** Where each stop looks from, its near and far planes, and the splash and raindrop radii there. */
27
+ const STOPS = {
28
+ cup: { body: 'cup', eye: [0.16, 0.98, 0.16], target: [0, 0.83, 0], near: 0.003, far: 400, splash: 0.005, drop: 0.002 },
29
+ puddle: { body: 'puddle', eye: [5.0, 0.9, 2.3], target: [4, 0, 1], near: 0.02, far: 2000, splash: 0.03, drop: 0.004 },
30
+ lake: { body: 'lake', eye: [22, 4, 188], target: [0, -1, 166], near: 0.1, far: 6000, splash: 0.3, drop: 0.01 },
31
+ ocean: { body: 'ocean', eye: [0, 9, 5000 + 150], target: [25, 0, 5000 + 230], near: 0.2, far: 12000, splash: 3, drop: 0.02 },
32
+ aerial: { body: 'ocean', eye: [700, 320, 4300], target: [0, 0, 5000], near: 0.5, far: 12000, splash: 3, drop: 0.02 },
33
+ };
34
+
35
+ async function main() {
36
+ const viewport = element("viewport"), graphics = new GraphicsEngine(), scene = new Scene();
37
+ viewport.appendChild(graphics.viewport.el);
38
+ const dataset = new EntityComponentDataset(), entities = new EntityManager();
39
+ const water_system = new WaterSystem(graphics, scene);
40
+ entities.addSystem(new ShadedGeometrySystem(graphics, scene));
41
+ entities.addSystem(new LightSystem(graphics, scene));
42
+ entities.addSystem(water_system);
43
+ entities.attachDataset(dataset);
44
+ await new Promise((resolve, reject) => entities.startup(resolve, reject));
45
+ const world = await build_world(dataset);
46
+ load_default_environment(scene);
47
+
48
+ const sun = new Light(); sun.intensity.set(2.4);
49
+ const sun_pose = new Transform64(), rotation = new Quaternion();
50
+ // low and ahead of the views, so its glitter path shows the slopes
51
+ rotation.fromUnitVectors(Vector3.forward, new Vector3(-0.15, -0.3, -0.94).normalize());
52
+ sun_pose.setRotation(rotation.x, rotation.y, rotation.z, rotation.w); sun_pose.updateMatrix();
53
+ new Entity().add(sun).add(sun_pose).build(dataset);
54
+
55
+ const camera = graphics.camera.camera, controller = new OrbitalCameraController(camera, viewport);
56
+ camera.fov = Math.PI / 3;
57
+ let stop = STOPS.cup;
58
+ function go(name) {
59
+ stop = STOPS[name];
60
+ camera.near = stop.near; camera.far = stop.far;
61
+ controller.look(new Vector3(...stop.eye), new Vector3(...stop.target));
62
+ for (const button of document.querySelectorAll("button.stop")) { button.style.borderColor = button.dataset.stop === name ? "#8dd3db" : ""; }
63
+ }
64
+ function configure() {
65
+ const lines = [];
66
+ for (const [name, body] of Object.entries(world.bodies)) {
67
+ body.waves.windSpeed.set(body.base_wind * number("wind"));
68
+ body.waves.windDirection.set(number("direction") * Math.PI / 180);
69
+ lines.push(`${name.padEnd(7)} ${(body.base_wind * number("wind")).toFixed(1)} m/s${body.waves.upwindFetch.getValue() > 0 ? `, ${body.waves.upwindFetch.getValue() / 1000} km of sea upwind` : ''}`);
70
+ }
71
+ element("winds").textContent = lines.join("\n");
72
+ }
73
+ const report = message => { element("status").textContent = message; };
74
+ for (const id of ["wind", "direction"]) { element(id).addEventListener("input", configure); }
75
+ for (const button of document.querySelectorAll("button.stop")) { button.onclick = () => go(button.dataset.stop); }
76
+ configure(); go("cup");
77
+
78
+ // a click splashes where its ray meets the stop's body at rest
79
+ const inverse = new Float64Array(16);
80
+ function splash_at(u, v, radius) {
81
+ const body = world.bodies[stop.body];
82
+ if (!m4_invert(inverse, camera.view_projection_matrix)) { return; }
83
+ const unproject = z => {
84
+ const x = 2 * u - 1, y = 1 - 2 * v;
85
+ const w = inverse[3] * x + inverse[7] * y + inverse[11] * z + inverse[15];
86
+ return [0, 1, 2].map(i => (inverse[i] * x + inverse[4 + i] * y + inverse[8 + i] * z + inverse[12 + i]) / w);
87
+ };
88
+ const near = unproject(1), far = unproject(0.5);
89
+ const direction = far.map((value, i) => value - near[i]);
90
+ if (Math.abs(direction[1]) < 1e-9) { return; }
91
+ const t = (body.level - near[1]) / direction[1];
92
+ if (!(t > 0)) { return; }
93
+ water_system.splash(body.entity, near.map((value, i) => value + direction[i] * t), radius, number("kick"));
94
+ }
95
+ viewport.addEventListener("click", event => {
96
+ const rect = viewport.getBoundingClientRect();
97
+ splash_at((event.clientX - rect.left) / rect.width, (event.clientY - rect.top) / rect.height, stop.splash);
98
+ });
99
+
100
+ let paused = false, ready = false, rain_debt = 0;
101
+ element("pause").onclick = () => { paused = !paused; element("pause").textContent = paused ? "Resume" : "Pause"; };
102
+ graphics.on.contextFailed.add(error => report(error.message));
103
+ graphics.on.contextLost.add(error => { ready = false; report(`GPU device lost · ${error.message}`); });
104
+ await graphics.start();
105
+ const renderer = graphics.renderer;
106
+ renderer.graphics.device.addEventListener("uncapturederror", event => { ready = false; report(event.error.message); console.error(event.error.message); });
107
+ const profile = install_profile_hotkey({ renderer, name: "water_surface", status: element("status"), target: viewport,
108
+ settings: () => [stop.body, `wind × ${number("wind")}`, element("rain").checked ? `rain ${number("rate")}/s` : 'no rain'] });
109
+ element("profile").onclick = () => profile.toggle().catch(error => report(error.message));
110
+
111
+ element("measure").onclick = async () => {
112
+ element("report").textContent = "recording…";
113
+ const session = new GPUProfileSession({ level: GPUProfileLevel.WORKLOAD, note: 'water_surface measure' });
114
+ renderer.profile_session = session; session.start();
115
+ await new Promise(resolve => setTimeout(resolve, 2500));
116
+ renderer.profile_session = null;
117
+ const bytes = await session.stop();
118
+ const capture = sgpt_read_capture(bytes instanceof ArrayBuffer ? bytes : bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength));
119
+ const sums = new Map();
120
+ let frames = 0, total = 0;
121
+ for (const frame of capture.frames) {
122
+ if (!frame.spans || frame.spans.length === 0) { continue; }
123
+ frames++;
124
+ for (const span of frame.spans) {
125
+ total += span.duration_ns;
126
+ if (!/^Water \/ (spectrum|waves|particles|classify)/.test(span.label)) { continue; }
127
+ sums.set(span.label, (sums.get(span.label) ?? 0) + span.duration_ns);
128
+ }
129
+ }
130
+ const rows = [...sums.entries()].sort((a, b) => b[1] - a[1]);
131
+ const surface = rows.reduce((sum, [, ns]) => sum + ns, 0);
132
+ element("report").textContent = [`${frames} frames · every pass ${(total / frames / 1000).toFixed(0)} µs · surface ${(surface / frames / 1000).toFixed(1)} µs`,
133
+ ...rows.map(([label, ns]) => `${(ns / frames / 1000).toFixed(1).padStart(7)} ${label.replace('Water / ', '')}`)].join("\n");
134
+ };
135
+
136
+ ready = true; report("Ready · click the water to splash");
137
+ Object.assign(globalThis, { graphics, scene, dataset, entities, world, water_system, camera, controller,
138
+ water_surface_playground: { go, splash_at, get ready() { return ready; } } });
139
+
140
+ create_frame_loop(raw_dt => {
141
+ if (!ready) { return; }
142
+ const dt = paused ? 0 : Math.min(raw_dt, 0.05);
143
+ if (element("rain").checked && dt > 0) {
144
+ rain_debt += number("rate") * dt;
145
+ for (; rain_debt >= 1; rain_debt--) { splash_at(Math.random(), 0.3 + 0.7 * Math.random(), stop.drop); }
146
+ }
147
+ graphics.viewport.size.set(Math.max(1, viewport.clientWidth), Math.max(1, viewport.clientHeight));
148
+ controller.update();
149
+ entities.update(dt);
150
+ graphics.render(dt);
151
+ }, 60);
152
+ }
153
+
154
+ main().catch(error => { console.error(error); element("status").textContent = error.message; });
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Four bodies of water, from a cup to an ocean, each a `Water` + `WaterWaves` entity whose mesh authors
3
+ * only its outline: the surface's detail comes from the waves, at any scale.
4
+ */
5
+ export function build_world(dataset: any): Promise<{
6
+ bodies: {
7
+ cup: {
8
+ entity: any;
9
+ water: Water;
10
+ waves: WaterWaves;
11
+ transform: Transform64;
12
+ level: any;
13
+ base_wind: any;
14
+ };
15
+ puddle: {
16
+ entity: any;
17
+ water: Water;
18
+ waves: WaterWaves;
19
+ transform: Transform64;
20
+ level: any;
21
+ base_wind: any;
22
+ };
23
+ lake: {
24
+ entity: any;
25
+ water: Water;
26
+ waves: WaterWaves;
27
+ transform: Transform64;
28
+ level: any;
29
+ base_wind: any;
30
+ };
31
+ ocean: {
32
+ entity: any;
33
+ water: Water;
34
+ waves: WaterWaves;
35
+ transform: Transform64;
36
+ level: any;
37
+ base_wind: any;
38
+ };
39
+ };
40
+ }>;
41
+ import Water from "../../../engine/graphics/ecs/water/Water.js";
42
+ import WaterWaves from "../../../engine/graphics/ecs/water/WaterWaves.js";
43
+ import { Transform64 } from "../../../engine/ecs/transform/Transform64.js";
44
+ //# sourceMappingURL=world.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../../../../../src/shade/playground/water_surface/world.js"],"names":[],"mappings":"AAsGA;;;GAGG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDC;kBA3JiB,6CAA6C;uBACxC,kDAAkD;4BAH7C,8CAA8C"}