@woosh/meep-engine 3.64.1 → 3.65.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 (324) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/build/bundle-worker-image-decoder.js +1 -1
  3. package/build/bundle-worker-terrain.js +1 -1
  4. package/package.json +1 -1
  5. package/src/core/binary/BinaryBuffer.d.ts +5 -0
  6. package/src/core/binary/BinaryBuffer.d.ts.map +1 -1
  7. package/src/core/binary/BinaryBuffer.js +39 -5
  8. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.d.ts +65 -6
  9. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.d.ts.map +1 -1
  10. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.js +451 -101
  11. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts +4 -2
  12. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts.map +1 -1
  13. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +4 -2
  14. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.d.ts +8 -1
  15. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.d.ts.map +1 -1
  16. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.js +45 -10
  17. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.d.ts.map +1 -1
  18. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.js +237 -119
  19. package/src/engine/graphics/ecs/grass/GrassSpecies.d.ts +143 -0
  20. package/src/engine/graphics/ecs/grass/GrassSpecies.d.ts.map +1 -0
  21. package/src/engine/graphics/ecs/grass/GrassSpecies.js +189 -0
  22. package/src/engine/graphics/ecs/grass/GrassSurface.d.ts +25 -0
  23. package/src/engine/graphics/ecs/grass/GrassSurface.d.ts.map +1 -0
  24. package/src/engine/graphics/ecs/grass/GrassSurface.js +32 -0
  25. package/src/engine/graphics/ecs/grass/GroundCover.d.ts +68 -0
  26. package/src/engine/graphics/ecs/grass/GroundCover.d.ts.map +1 -0
  27. package/src/engine/graphics/ecs/grass/GroundCover.js +85 -0
  28. package/src/engine/graphics3/GrassSurfaceSystem.d.ts +153 -0
  29. package/src/engine/graphics3/GrassSurfaceSystem.d.ts.map +1 -0
  30. package/src/engine/graphics3/GrassSurfaceSystem.js +1076 -0
  31. package/src/engine/graphics3/GroundCoverSystem.d.ts +33 -0
  32. package/src/engine/graphics3/GroundCoverSystem.d.ts.map +1 -0
  33. package/src/engine/graphics3/GroundCoverSystem.js +58 -0
  34. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  35. package/src/engine/network/NetworkSession.js +372 -110
  36. package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
  37. package/src/engine/network/orchestrator/NetworkPeer.js +6 -1
  38. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
  39. package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +9 -2
  40. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
  41. package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +325 -140
  42. package/src/engine/network/sim/SimActionExecutor.d.ts +4 -1
  43. package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
  44. package/src/engine/network/sim/SimActionExecutor.js +65 -9
  45. package/src/engine/network/state/PredictionHistory.d.ts.map +1 -1
  46. package/src/engine/network/state/PredictionHistory.js +6 -1
  47. package/src/engine/network/time/AdaptiveRenderDelay.d.ts +25 -14
  48. package/src/engine/network/time/AdaptiveRenderDelay.d.ts.map +1 -1
  49. package/src/engine/network/time/AdaptiveRenderDelay.js +38 -20
  50. package/src/engine/network/time/RenderPlayout.d.ts +23 -3
  51. package/src/engine/network/time/RenderPlayout.d.ts.map +1 -1
  52. package/src/engine/network/time/RenderPlayout.js +40 -4
  53. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  54. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.d.ts +5 -1
  55. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.d.ts.map +1 -1
  56. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.js +27 -1
  57. package/src/shade/device/shader/ShaderModuleCompiler.d.ts +2 -0
  58. package/src/shade/device/shader/ShaderModuleCompiler.d.ts.map +1 -1
  59. package/src/shade/device/shader/ShaderModuleCompiler.js +25 -2
  60. package/src/shade/playground/grass_surfaces/index.html +75 -0
  61. package/src/shade/playground/grass_surfaces/main.d.ts +2 -0
  62. package/src/shade/playground/grass_surfaces/main.d.ts.map +1 -0
  63. package/src/shade/playground/grass_surfaces/main.js +593 -0
  64. package/src/shade/playground/grass_surfaces/read_grass_surfaces.d.ts +62 -0
  65. package/src/shade/playground/grass_surfaces/read_grass_surfaces.d.ts.map +1 -0
  66. package/src/shade/playground/grass_surfaces/read_grass_surfaces.js +188 -0
  67. package/src/shade/playground/probe_clipmap_box/README.md +5 -1
  68. package/src/shade/playground/probe_clipmap_box/index.html +12 -0
  69. package/src/shade/playground/probe_clipmap_box/main.d.ts.map +1 -1
  70. package/src/shade/playground/probe_clipmap_box/main.js +15 -0
  71. package/src/shade/playground/probe_clipmap_box/scene.d.ts +8 -1
  72. package/src/shade/playground/probe_clipmap_box/scene.d.ts.map +1 -1
  73. package/src/shade/playground/probe_clipmap_box/scene.js +74 -6
  74. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  75. package/src/shade/renderer/Renderer.js +47 -43
  76. package/src/shade/renderer/extension/ViewTextures.d.ts +12 -5
  77. package/src/shade/renderer/extension/ViewTextures.d.ts.map +1 -1
  78. package/src/shade/renderer/extension/ViewTextures.js +19 -5
  79. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +3 -1
  80. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts.map +1 -1
  81. package/src/shade/renderer/fluid/GPUFluidCascadeStack.js +6 -1
  82. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +7 -0
  83. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts.map +1 -1
  84. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.js +10 -0
  85. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +7 -1
  86. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  87. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +46 -15
  88. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.d.ts +3 -2
  89. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.d.ts.map +1 -1
  90. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.js +3 -2
  91. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.d.ts +22 -0
  92. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.d.ts.map +1 -0
  93. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.js +247 -0
  94. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +50 -0
  95. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  96. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +101 -0
  97. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts +2 -1
  98. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts.map +1 -1
  99. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.js +2 -1
  100. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts +8 -0
  101. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts.map +1 -1
  102. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.js +12 -0
  103. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts +12 -6
  104. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts.map +1 -1
  105. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.js +35 -29
  106. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_clipmap.d.ts.map +1 -1
  107. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_clipmap.js +4 -2
  108. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_material.d.ts.map +1 -1
  109. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_material.js +6 -4
  110. package/src/shade/renderer/global_illumination/probe_clipmap/material/GPUBrickMaterial.d.ts.map +1 -1
  111. package/src/shade/renderer/global_illumination/probe_clipmap/material/GPUBrickMaterial.js +2 -1
  112. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.d.ts +6 -5
  113. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.d.ts.map +1 -1
  114. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.js +15 -14
  115. package/src/shade/renderer/global_illumination/probe_clipmap/material/shader_brick_material_gather.d.ts.map +1 -1
  116. package/src/shade/renderer/global_illumination/probe_clipmap/material/shader_brick_material_gather.js +4 -2
  117. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +19 -2
  118. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  119. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +128 -10
  120. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +19 -1
  121. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  122. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +27 -2
  123. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts +19 -11
  124. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts.map +1 -1
  125. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.js +35 -11
  126. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  127. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +3 -1
  128. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.d.ts +40 -0
  129. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.d.ts.map +1 -0
  130. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.js +174 -0
  131. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_material.d.ts +4 -4
  132. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_material.js +10 -10
  133. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.d.ts +31 -0
  134. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.d.ts.map +1 -0
  135. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.js +54 -0
  136. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts +8 -4
  137. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
  138. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +10 -21
  139. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts +7 -2
  140. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts.map +1 -1
  141. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.js +33 -29
  142. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.d.ts +28 -0
  143. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.d.ts.map +1 -0
  144. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.js +138 -0
  145. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts +13 -9
  146. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts.map +1 -1
  147. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js +18 -11
  148. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.js +1 -1
  149. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.d.ts.map +1 -1
  150. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js +4 -2
  151. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts.map +1 -1
  152. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js +2 -3
  153. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts +5 -3
  154. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts.map +1 -1
  155. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js +15 -30
  156. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -1
  157. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
  158. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +4 -2
  159. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts +11 -0
  160. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts.map +1 -1
  161. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.js +29 -2
  162. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.d.ts +40 -0
  163. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.d.ts.map +1 -0
  164. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.js +126 -0
  165. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.d.ts +36 -0
  166. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.d.ts.map +1 -0
  167. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.js +221 -0
  168. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.d.ts +40 -0
  169. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.d.ts.map +1 -0
  170. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.js +86 -0
  171. package/src/shade/renderer/grass/blade/GPUGrassBlades.d.ts +135 -0
  172. package/src/shade/renderer/grass/blade/GPUGrassBlades.d.ts.map +1 -0
  173. package/src/shade/renderer/grass/blade/GPUGrassBlades.js +676 -0
  174. package/src/shade/renderer/grass/blade/GRASS_BLADE.d.ts +145 -0
  175. package/src/shade/renderer/grass/blade/GRASS_BLADE.d.ts.map +1 -0
  176. package/src/shade/renderer/grass/blade/GRASS_BLADE.js +179 -0
  177. package/src/shade/renderer/grass/blade/chunk_grass_blade.d.ts +63 -0
  178. package/src/shade/renderer/grass/blade/chunk_grass_blade.d.ts.map +1 -0
  179. package/src/shade/renderer/grass/blade/chunk_grass_blade.js +244 -0
  180. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.d.ts +58 -0
  181. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.d.ts.map +1 -0
  182. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.js +174 -0
  183. package/src/shade/renderer/grass/blade/grass_blade_id_draw.d.ts +25 -0
  184. package/src/shade/renderer/grass/blade/grass_blade_id_draw.d.ts.map +1 -0
  185. package/src/shade/renderer/grass/blade/grass_blade_id_draw.js +133 -0
  186. package/src/shade/renderer/grass/blade/grass_blade_mechanics.d.ts +80 -0
  187. package/src/shade/renderer/grass/blade/grass_blade_mechanics.d.ts.map +1 -0
  188. package/src/shade/renderer/grass/blade/grass_blade_mechanics.js +92 -0
  189. package/src/shade/renderer/grass/blade/grass_blade_resolve.d.ts +29 -0
  190. package/src/shade/renderer/grass/blade/grass_blade_resolve.d.ts.map +1 -0
  191. package/src/shade/renderer/grass/blade/grass_blade_resolve.js +175 -0
  192. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.d.ts +14 -0
  193. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.d.ts.map +1 -0
  194. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.js +45 -0
  195. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.d.ts +61 -0
  196. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.d.ts.map +1 -0
  197. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.js +340 -0
  198. package/src/shade/renderer/grass/blade/shader_grass_cell_count.d.ts +46 -0
  199. package/src/shade/renderer/grass/blade/shader_grass_cell_count.d.ts.map +1 -0
  200. package/src/shade/renderer/grass/blade/shader_grass_cell_count.js +280 -0
  201. package/src/shade/renderer/grass/population/chunk_grass_population.d.ts +60 -0
  202. package/src/shade/renderer/grass/population/chunk_grass_population.d.ts.map +1 -0
  203. package/src/shade/renderer/grass/population/chunk_grass_population.js +171 -0
  204. package/src/shade/renderer/grass/press/GPUGrassPress.d.ts +99 -0
  205. package/src/shade/renderer/grass/press/GPUGrassPress.d.ts.map +1 -0
  206. package/src/shade/renderer/grass/press/GPUGrassPress.js +436 -0
  207. package/src/shade/renderer/grass/press/GRASS_PRESS.d.ts +179 -0
  208. package/src/shade/renderer/grass/press/GRASS_PRESS.d.ts.map +1 -0
  209. package/src/shade/renderer/grass/press/GRASS_PRESS.js +217 -0
  210. package/src/shade/renderer/grass/press/chunk_grass_press.d.ts +65 -0
  211. package/src/shade/renderer/grass/press/chunk_grass_press.d.ts.map +1 -0
  212. package/src/shade/renderer/grass/press/chunk_grass_press.js +296 -0
  213. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts +31 -0
  214. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts.map +1 -0
  215. package/src/shade/renderer/grass/press/shader_grass_press_mark.js +169 -0
  216. package/src/shade/renderer/grass/press/shader_grass_press_stamp.d.ts +27 -0
  217. package/src/shade/renderer/grass/press/shader_grass_press_stamp.d.ts.map +1 -0
  218. package/src/shade/renderer/grass/press/shader_grass_press_stamp.js +183 -0
  219. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.d.ts +193 -0
  220. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.d.ts.map +1 -0
  221. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.js +1253 -0
  222. package/src/shade/renderer/grass/surface/GRASS_SURFACE.d.ts +211 -0
  223. package/src/shade/renderer/grass/surface/GRASS_SURFACE.d.ts.map +1 -0
  224. package/src/shade/renderer/grass/surface/GRASS_SURFACE.js +241 -0
  225. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.d.ts +82 -0
  226. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.d.ts.map +1 -0
  227. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.js +111 -0
  228. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.d.ts +39 -0
  229. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.d.ts.map +1 -0
  230. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.js +85 -0
  231. package/src/shade/renderer/grass/surface/chunk_grass_directory.d.ts +29 -0
  232. package/src/shade/renderer/grass/surface/chunk_grass_directory.d.ts.map +1 -0
  233. package/src/shade/renderer/grass/surface/chunk_grass_directory.js +112 -0
  234. package/src/shade/renderer/grass/surface/chunk_grass_slot.d.ts +27 -0
  235. package/src/shade/renderer/grass/surface/chunk_grass_slot.d.ts.map +1 -0
  236. package/src/shade/renderer/grass/surface/chunk_grass_slot.js +50 -0
  237. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.d.ts +21 -0
  238. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.d.ts.map +1 -0
  239. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.js +41 -0
  240. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.d.ts +32 -0
  241. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.d.ts.map +1 -0
  242. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.js +136 -0
  243. package/src/shade/renderer/grass/surface/chunk_grass_surfel.d.ts +37 -0
  244. package/src/shade/renderer/grass/surface/chunk_grass_surfel.d.ts.map +1 -0
  245. package/src/shade/renderer/grass/surface/chunk_grass_surfel.js +85 -0
  246. package/src/shade/renderer/grass/surface/chunk_grass_tile.d.ts +25 -0
  247. package/src/shade/renderer/grass/surface/chunk_grass_tile.d.ts.map +1 -0
  248. package/src/shade/renderer/grass/surface/chunk_grass_tile.js +52 -0
  249. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.d.ts +23 -0
  250. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.d.ts.map +1 -0
  251. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.js +87 -0
  252. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.d.ts +43 -0
  253. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.d.ts.map +1 -0
  254. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.js +265 -0
  255. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.d.ts +13 -0
  256. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.d.ts.map +1 -0
  257. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.js +49 -0
  258. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.d.ts +62 -0
  259. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.d.ts.map +1 -0
  260. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.js +162 -0
  261. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.d.ts +40 -0
  262. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.d.ts.map +1 -0
  263. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.js +155 -0
  264. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.d.ts +19 -0
  265. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.d.ts.map +1 -0
  266. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.js +58 -0
  267. package/src/shade/renderer/grass/surface/shader_grass_surface_want.d.ts +30 -0
  268. package/src/shade/renderer/grass/surface/shader_grass_surface_want.d.ts.map +1 -0
  269. package/src/shade/renderer/grass/surface/shader_grass_surface_want.js +251 -0
  270. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.d.ts +21 -0
  271. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.d.ts.map +1 -0
  272. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.js +75 -0
  273. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts.map +1 -1
  274. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.js +4 -23
  275. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.d.ts +12 -0
  276. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.d.ts.map +1 -0
  277. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.js +29 -0
  278. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
  279. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +22 -0
  280. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  281. package/src/shade/renderer/scene/GPUSceneContext.js +3 -0
  282. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.d.ts +27 -0
  283. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.d.ts.map +1 -0
  284. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.js +38 -0
  285. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.d.ts +28 -0
  286. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.d.ts.map +1 -0
  287. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.js +58 -0
  288. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.d.ts.map +1 -1
  289. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.js +8 -0
  290. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.d.ts +37 -0
  291. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.d.ts.map +1 -0
  292. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.js +148 -0
  293. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.d.ts +20 -0
  294. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.d.ts.map +1 -0
  295. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.js +169 -0
  296. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.d.ts +18 -0
  297. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.d.ts.map +1 -1
  298. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.js +28 -0
  299. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.d.ts +13 -0
  300. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.d.ts.map +1 -0
  301. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.js +22 -0
  302. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  303. package/src/shade/renderer/water/GPUWaterRenderer.js +4 -0
  304. package/src/shade/renderer/wind/GPUSceneWind.d.ts +52 -5
  305. package/src/shade/renderer/wind/GPUSceneWind.d.ts.map +1 -1
  306. package/src/shade/renderer/wind/GPUSceneWind.js +164 -8
  307. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.d.ts +3 -1
  308. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.d.ts.map +1 -1
  309. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.js +3 -1
  310. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts +2 -1
  311. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts.map +1 -1
  312. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.js +18 -13
  313. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.d.ts +13 -0
  314. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.d.ts.map +1 -0
  315. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.js +23 -0
  316. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.d.ts +1 -0
  317. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.d.ts.map +1 -1
  318. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.js +6 -1
  319. package/src/shade/renderer/wind/wind_field_add_resources.d.ts +11 -0
  320. package/src/shade/renderer/wind/wind_field_add_resources.d.ts.map +1 -1
  321. package/src/shade/renderer/wind/wind_field_add_resources.js +15 -0
  322. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +1 -1
  323. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  324. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +2 -0
@@ -0,0 +1,676 @@
1
+ import { assert } from "../../../../core/assert.js";
2
+ import { TextureViewDescriptor } from "../../../descriptor/texture/TextureViewDescriptor.js";
3
+ import { BufferResourceDescriptor } from "../../../device/graph/BufferResourceDescriptor.js";
4
+ import { TextureResourceDescriptor } from "../../../device/graph/TextureResourceDescriptor.js";
5
+ import { graph_read_buffer } from "../../buffer/graph_read_buffer.js";
6
+ import { DEFAULT_DEPTH_TEXTURE_VIEW } from "../../depth/DEFAULT_DEPTH_TEXTURE_VIEW.js";
7
+ import { GBufferTextures } from "../../extension/GBufferTextures.js";
8
+ import { ViewTextures } from "../../extension/ViewTextures.js";
9
+ import { INDIRECT_COMPUTE_COMMAND_DESCRIPTOR } from "../../gpu_primitive/indirect/IndirectComputeCommandBuildPass.js";
10
+ import { view_velocity_matrices } from "../../postprocess/velocity/view_velocity_matrices.js";
11
+ import {
12
+ graph_prefix_scan_csdldf,
13
+ prefix_scan_csdldf_output_descriptor
14
+ } from "../../gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js";
15
+ import { shader_prefix_sum_to_command } from "../../rasterize/expand/mesh/shader_prefix_sum_to_command.js";
16
+ import { graph_create_buffer } from "../../shader/graph/graph_create_buffer.js";
17
+ import { GPUGrassPress } from "../press/GPUGrassPress.js";
18
+ import { GRASS_BLADE_CLOCK_STRUCT } from "./chunk_grass_blade_wind.js";
19
+ import { grass_blade_compliance, grass_blade_frequency } from "./grass_blade_mechanics.js";
20
+ import {
21
+ GRASS_BLADE_CAPACITY_LIMIT,
22
+ GRASS_BLADE_ID_FORMAT,
23
+ GRASS_BLADE_ID_NONE,
24
+ GRASS_BLADE_LIST_COUNT,
25
+ GRASS_BLADE_LIST_HEADER_WORDS,
26
+ GRASS_BLADE_RECORD_WORDS,
27
+ GRASS_CELL_WORDS,
28
+ GRASS_SPECIES_WORDS
29
+ } from "./GRASS_BLADE.js";
30
+ import { GRASS_BLADE_ID_PIPELINE, GRASS_BLADE_ID_RESOURCES } from "./grass_blade_id_draw.js";
31
+ import { GRASS_BLADE_RESOLVE_PIPELINE, GRASS_BLADE_RESOLVE_RESOURCES } from "./grass_blade_resolve.js";
32
+ import { shader_grass_blade_draw_args } from "./shader_grass_blade_draw_args.js";
33
+ import { shader_grass_blade_expand } from "./shader_grass_blade_expand.js";
34
+ import { GRASS_CELL_COUNT_WORKGROUP_SIZE, shader_grass_cell_count } from "./shader_grass_cell_count.js";
35
+
36
+ /**
37
+ * @typedef {import("../../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} FrameGraph
38
+ * @typedef {import("../../../device/pipeline/PipelineEnquiry.js").PipelineEnquiry} PipelineEnquiry
39
+ * @typedef {import("../../extension/FrameContext.js").FrameContext} FrameContext
40
+ * @typedef {import("../../fluid/forcing/GPUFluidForcing.js").GPUFluidForcing} GPUFluidForcing
41
+ * @typedef {import("../../GraphicsContext.js").GraphicsContext} GraphicsContext
42
+ * @typedef {import("../../view/GPUViewContext.js").GPUViewContext} GPUViewContext
43
+ * @typedef {import("../surface/GPUGrassSurfaces.js").GPUGrassSurfaces} GPUGrassSurfaces
44
+ */
45
+
46
+ /**
47
+ * Bytes at the front of a `u32` collection: its count, padded to the elements' alignment.
48
+ * @type {number}
49
+ */
50
+ const COLLECTION_HEADER_BYTES = 16;
51
+
52
+ /**
53
+ * Blades the frame's list is first made with room for.
54
+ * @type {number}
55
+ */
56
+ const INITIAL_BLADE_CAPACITY = 2 ** 17;
57
+
58
+ /**
59
+ * Species the species list is made with room for.
60
+ * @type {number}
61
+ */
62
+ const INITIAL_SPECIES_CAPACITY = 16;
63
+
64
+ const MIP_0 = TextureViewDescriptor.from({ mipLevelCount: 1, baseMipLevel: 0 });
65
+
66
+ /**
67
+ * Bytes of a `u32` collection with room for `count` elements.
68
+ *
69
+ * @param {number} count
70
+ * @returns {number}
71
+ */
72
+ function collection_size(count) {
73
+ return COLLECTION_HEADER_BYTES + Math.max(1, Math.ceil(count / 4)) * 16;
74
+ }
75
+
76
+ /**
77
+ * A view's blades for the frame being recorded: the handles its draw reads.
78
+ */
79
+ class BladeProduct {
80
+ /** @type {number} the closed blade list */
81
+ blades = -1;
82
+
83
+ /** @type {number} the draw's indirect arguments */
84
+ draw_args = -1;
85
+ }
86
+
87
+ /**
88
+ * Grass blades on the device: the species list, and the passes that make a view's blades each frame and
89
+ * draw them (`GRASS_BLADE.js`).
90
+ *
91
+ * Blades stand on the surfels {@link GPUGrassSurfaces} keeps; nothing of a blade outlives its frame.
92
+ *
93
+ * Each frame: {@link update} once; then for every view that draws grass {@link graph_generate}, after the
94
+ * surfaces' own passes for the view, after whatever publishes the scene's wind for the frame (the blades
95
+ * are bent by it), and before anything reads the scene's depth for the frame's image; and
96
+ * {@link graph_draw} at the frame phase where the G-buffer is written into.
97
+ *
98
+ * The blades are pushed over by the scene's fluid obstacles through {@link press}, a field this owns and
99
+ * stamps as part of making a view's blades.
100
+ */
101
+ export class GPUGrassBlades {
102
+
103
+ /**
104
+ * Offer the pipelines the blades' passes run — see {@link PipelineEnquiry}.
105
+ *
106
+ * @param {PipelineEnquiry} enquiry
107
+ */
108
+ static enquirePipelines(enquiry) {
109
+ enquiry.compute.push(shader_grass_cell_count.pipeline);
110
+ enquiry.compute.push(shader_grass_blade_expand.pipeline);
111
+ enquiry.compute.push(shader_grass_blade_draw_args.pipeline);
112
+ enquiry.compute.push(shader_prefix_sum_to_command.pipeline);
113
+ enquiry.render.push(GRASS_BLADE_ID_PIPELINE);
114
+ enquiry.render.push(GRASS_BLADE_RESOLVE_PIPELINE);
115
+
116
+ GPUGrassPress.enquirePipelines(enquiry);
117
+ }
118
+
119
+ /**
120
+ * Where obstacles have pressed the grass down, and its settings.
121
+ *
122
+ * @readonly
123
+ * @type {GPUGrassPress}
124
+ */
125
+ press;
126
+
127
+ /** @type {GPUDevice} */
128
+ #device;
129
+
130
+ /** @type {GPUGrassSurfaces} */
131
+ #surfaces;
132
+
133
+ /**
134
+ * The species list, a record a species, by the species' index.
135
+ * @type {Float32Array}
136
+ */
137
+ #species = new Float32Array(INITIAL_SPECIES_CAPACITY * GRASS_SPECIES_WORDS);
138
+
139
+ /** @type {GPUBuffer|null} the device's copy of {@link #species} */
140
+ #species_buffer = null;
141
+
142
+ /**
143
+ * Whether the device's copy is behind.
144
+ * @type {boolean}
145
+ */
146
+ #species_dirty = true;
147
+
148
+ /**
149
+ * The scene's clock as the blades' pass reads it (`GRASS_BLADE_CLOCK_STRUCT`): this frame's, then the
150
+ * frame before's.
151
+ * @type {ArrayBuffer}
152
+ */
153
+ #clock = new ArrayBuffer(GRASS_BLADE_CLOCK_STRUCT.size);
154
+ #clock_u32 = new Uint32Array(this.#clock);
155
+ #clock_f32 = new Float32Array(this.#clock);
156
+
157
+ /** @type {GPUBuffer|null} the device's copy of {@link #clock} */
158
+ #clock_buffer = null;
159
+
160
+ /**
161
+ * Seconds of the scene's clock past its whole seconds, kept in f64.
162
+ * @type {number}
163
+ */
164
+ #clock_fraction = 0;
165
+
166
+ /**
167
+ * Blades a frame's list has room for.
168
+ * @type {number}
169
+ */
170
+ #blade_capacity = INITIAL_BLADE_CAPACITY;
171
+
172
+ /**
173
+ * The most blades any view's list was asked to hold, as last read off the device.
174
+ * @type {number}
175
+ */
176
+ #blades_asked = 0;
177
+
178
+ /**
179
+ * Each view's blades for the frame being recorded, from its generation to its draw.
180
+ * @type {Map<GPUViewContext, BladeProduct>}
181
+ */
182
+ #products = new Map();
183
+
184
+ /**
185
+ * @param {GraphicsContext} graphics
186
+ * @param {GPUGrassSurfaces} surfaces whose surfels the blades stand on
187
+ */
188
+ constructor(graphics, surfaces) {
189
+ assert.defined(graphics, 'graphics');
190
+ assert.equal(graphics.isGraphicsContext, true, 'graphics.isGraphicsContext !== true');
191
+ assert.defined(surfaces, 'surfaces');
192
+
193
+ this.#device = graphics.device;
194
+ this.#surfaces = surfaces;
195
+
196
+ this.press = new GPUGrassPress(graphics);
197
+ }
198
+
199
+ /**
200
+ * @returns {number} blades a frame's list has room for
201
+ */
202
+ get blade_capacity() {
203
+ return this.#blade_capacity;
204
+ }
205
+
206
+ /**
207
+ * @returns {number} the most blades a view's list was asked to hold, as last read off the device
208
+ */
209
+ get blades_asked() {
210
+ return this.#blades_asked;
211
+ }
212
+
213
+ /**
214
+ * The species list on the device. Null before the first {@link update}, and replaced when it grows.
215
+ *
216
+ * @returns {GPUBuffer|null}
217
+ */
218
+ get species_buffer() {
219
+ return this.#species_buffer;
220
+ }
221
+
222
+ /**
223
+ * The blades' clock on the device (`GRASS_BLADE_CLOCK_STRUCT`). Null before the first {@link update}.
224
+ *
225
+ * @returns {GPUBuffer|null}
226
+ */
227
+ get clock_buffer() {
228
+ return this.#clock_buffer;
229
+ }
230
+
231
+ /**
232
+ * Set a species' record.
233
+ *
234
+ * @param {number} index the species' place in the list, as `mesh_ground_covers` rows name it
235
+ * @param {object} species
236
+ * @param {number} species.blade_length metres
237
+ * @param {number} species.blade_width metres
238
+ * @param {number} species.density blades a square metre
239
+ * @param {number} species.roughness
240
+ * @param {number[]} species.color_root linear rgb
241
+ * @param {number[]} species.color_tip linear rgb
242
+ * @param {number} species.length_variation how much of its length a blade can lack, 0 to 1
243
+ * @param {number} species.lean the most a blade leans from upright at its root, radians
244
+ * @param {number} species.curl the most a blade's tip turns further than its root leans, radians
245
+ * @param {number} species.tint how far a blade's colour strays from its species', as a share of it
246
+ * @param {number} species.roundness how far a blade's normal turns towards its edges
247
+ * @param {number} species.elastic_modulus of the blade's tissue in bending, Pa
248
+ * @param {number} species.blade_depth depth of the blade's section in bending, metres
249
+ * @param {number} species.turbulence how unsteady the wind a blade feels is, as a share of its speed
250
+ */
251
+ set_species(index, species) {
252
+ assert.isNonNegativeInteger(index, 'index');
253
+
254
+ if ((index + 1) * GRASS_SPECIES_WORDS > this.#species.length) {
255
+ const grown = new Float32Array(Math.max(this.#species.length * 2, (index + 1) * GRASS_SPECIES_WORDS));
256
+
257
+ grown.set(this.#species);
258
+
259
+ this.#species = grown;
260
+ }
261
+
262
+ const words = this.#species;
263
+ const at = index * GRASS_SPECIES_WORDS;
264
+
265
+ words[at] = species.blade_length;
266
+ words[at + 1] = species.blade_width;
267
+ words[at + 2] = species.density;
268
+ words[at + 3] = species.roughness;
269
+
270
+ words[at + 4] = species.color_root[0];
271
+ words[at + 5] = species.color_root[1];
272
+ words[at + 6] = species.color_root[2];
273
+ words[at + 7] = species.length_variation;
274
+
275
+ words[at + 8] = species.color_tip[0];
276
+ words[at + 9] = species.color_tip[1];
277
+ words[at + 10] = species.color_tip[2];
278
+ words[at + 11] = species.lean;
279
+
280
+ words[at + 12] = species.curl;
281
+ words[at + 13] = species.tint;
282
+ words[at + 14] = species.roundness;
283
+ words[at + 15] = 0;
284
+
285
+ words[at + 16] = grass_blade_compliance(species.elastic_modulus, species.blade_depth);
286
+ words[at + 17] = grass_blade_frequency(species.elastic_modulus, species.blade_depth);
287
+ words[at + 18] = species.turbulence;
288
+ words[at + 19] = species.recovery_time;
289
+
290
+ this.#species_dirty = true;
291
+ }
292
+
293
+ /**
294
+ * Begin a frame: move the blades' clock and the press's on, bring the device's species list up to
295
+ * date, and make room for the blades the last frames' lists were asked to hold. Call once a frame,
296
+ * before any view's {@link graph_generate}.
297
+ *
298
+ * @param {number} time_delta_seconds how far the scene's clock has moved since the last call
299
+ */
300
+ update(time_delta_seconds) {
301
+ assert.isNumber(time_delta_seconds, 'time_delta_seconds');
302
+ assert.greaterThanOrEqual(time_delta_seconds, 0, 'time_delta_seconds');
303
+
304
+ const device = this.#device;
305
+
306
+ // what was this frame's time is the frame before's
307
+ this.#clock_u32[2] = this.#clock_u32[0];
308
+ this.#clock_f32[3] = this.#clock_f32[1];
309
+
310
+ const fraction = this.#clock_fraction + time_delta_seconds;
311
+ const whole = Math.floor(fraction);
312
+
313
+ this.#clock_fraction = fraction - whole;
314
+
315
+ // whole seconds wrap with the word that holds them, as the sway's integer product does
316
+ this.#clock_u32[0] = (this.#clock_u32[0] + whole) >>> 0;
317
+ this.#clock_f32[1] = this.#clock_fraction;
318
+
319
+ if (this.#clock_buffer === null) {
320
+ this.#clock_buffer = device.createBuffer({
321
+ label: "grass / blade clock",
322
+ size: GRASS_BLADE_CLOCK_STRUCT.size,
323
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
324
+ });
325
+ }
326
+
327
+ device.queue.writeBuffer(this.#clock_buffer, 0, this.#clock);
328
+
329
+ if (this.#species_buffer === null || this.#species_buffer.size < this.#species.byteLength) {
330
+ this.#species_buffer?.destroy();
331
+
332
+ this.#species_buffer = device.createBuffer({
333
+ label: "grass / species",
334
+ size: this.#species.byteLength,
335
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
336
+ });
337
+
338
+ this.#species_dirty = true;
339
+ }
340
+
341
+ if (this.#species_dirty) {
342
+ this.#species_dirty = false;
343
+
344
+ device.queue.writeBuffer(this.#species_buffer, 0, this.#species);
345
+ }
346
+
347
+ // a list that was asked for more than it holds doubles until it holds what was asked
348
+ while (this.#blades_asked > this.#blade_capacity && this.#blade_capacity < GRASS_BLADE_CAPACITY_LIMIT) {
349
+ this.#blade_capacity = Math.min(this.#blade_capacity * 2, GRASS_BLADE_CAPACITY_LIMIT);
350
+ }
351
+
352
+ this.press.update(time_delta_seconds);
353
+
354
+ this.#products.clear();
355
+ }
356
+
357
+ /**
358
+ * Record the passes that make a view's blades: stamp the press field, count the cells, sum, and make
359
+ * the blades the counts allow. Records nothing while nothing grows.
360
+ *
361
+ * @param {object} options
362
+ * @param {FrameGraph} options.graph
363
+ * @param {GPUViewContext} options.view the view; its scene is the surfaces' scene
364
+ * @param {GPUFluidForcing|null} [options.forcing] the scene's GPU fluid forcing, whose obstacles press
365
+ * the blades; none press without it
366
+ */
367
+ graph_generate({ graph, view, forcing = null }) {
368
+ assert.defined(graph, 'graph');
369
+ assert.defined(view, 'view');
370
+
371
+ const surfaces = this.#surfaces;
372
+ const settings = surfaces.view_settings(view);
373
+
374
+ if (settings === null || this.#species_buffer === null) {
375
+ return;
376
+ }
377
+
378
+ const blade_capacity = this.#blade_capacity;
379
+
380
+ settings.blade_capacity = blade_capacity;
381
+
382
+ const slot_capacity = settings.slot_capacity;
383
+ const scene = view.scene;
384
+ const camera = view.camera;
385
+
386
+ const press_field = this.press.graph_stamp({ graph, view, forcing });
387
+
388
+ graph.push_scope("grass blades");
389
+
390
+ const cell_data = {};
391
+
392
+ const cell_pass = graph.add("count cells", cell_data, (data, resources, context) => {
393
+ shader_grass_cell_count.dispatch({
394
+ encoder: context.encoder,
395
+ group_count_x: Math.ceil(slot_capacity / GRASS_CELL_COUNT_WORKGROUP_SIZE),
396
+ bindings: {
397
+ settings,
398
+ camera: camera.gpu_buffer,
399
+ scene_database: scene.scene_database_buffer,
400
+ grass_pool: surfaces.pool_buffer,
401
+ grass_directory: surfaces.directory_buffer,
402
+ grass_cell_counts: resources.get(data.counts),
403
+ grass_cells: resources.get(data.cells),
404
+ },
405
+ });
406
+ });
407
+
408
+ cell_data.counts = cell_pass.create("cell counts", BufferResourceDescriptor.from(
409
+ collection_size(slot_capacity),
410
+ GPUBufferUsage.STORAGE,
411
+ // the count, which thread 0 writes
412
+ 0, COLLECTION_HEADER_BYTES,
413
+ ));
414
+
415
+ cell_data.cells = cell_pass.create("cells", BufferResourceDescriptor.from(
416
+ slot_capacity * GRASS_CELL_WORDS * 4,
417
+ GPUBufferUsage.STORAGE,
418
+ ));
419
+
420
+ const sums = graph_prefix_scan_csdldf({
421
+ graph,
422
+ input: cell_data.counts,
423
+ output: graph_create_buffer(graph, "cell offsets", prefix_scan_csdldf_output_descriptor(slot_capacity)),
424
+ element_max_count: slot_capacity,
425
+ });
426
+
427
+ const command_data = {};
428
+
429
+ const command_pass = graph.add("make blade command", command_data, (data, resources, context) => {
430
+ shader_prefix_sum_to_command.dispatch({
431
+ encoder: context.encoder,
432
+ bindings: {
433
+ prefix_sums: resources.get(data.prefix_sums),
434
+ command: resources.get(data.command),
435
+ },
436
+ });
437
+ });
438
+
439
+ command_data.prefix_sums = command_pass.read(sums);
440
+ command_data.command = command_pass.create("blade command", INDIRECT_COMPUTE_COMMAND_DESCRIPTOR);
441
+
442
+ const expand_data = {};
443
+
444
+ const expand_pass = graph.add("make blades", expand_data, (data, resources, context) => {
445
+ const bindings = {
446
+ settings,
447
+ camera: camera.gpu_buffer,
448
+ scene_database: scene.scene_database_buffer,
449
+ prefix_sums: resources.get(data.prefix_sums),
450
+ grass_cells: resources.get(data.cells),
451
+ grass_species: this.#species_buffer,
452
+ grass_surfels: surfaces.atlas_view,
453
+ grass_blades: resources.get(data.blades),
454
+ grass_clock: this.#clock_buffer,
455
+ grass_press: resources.get(data.press),
456
+ };
457
+
458
+ this.press.bind(bindings);
459
+
460
+ // the wind as it is and as the frame before read it
461
+ scene.wind.bind_history(bindings);
462
+
463
+ shader_grass_blade_expand.dispatchIndirect({
464
+ encoder: context.encoder,
465
+ command: resources.get(data.command),
466
+ bindings,
467
+ });
468
+ });
469
+
470
+ expand_data.command = expand_pass.read(command_data.command);
471
+ expand_data.prefix_sums = expand_pass.read(sums);
472
+ expand_data.cells = expand_pass.read(cell_data.cells);
473
+ expand_data.press = expand_pass.read(press_field);
474
+ expand_data.blades = expand_pass.create("blade list", BufferResourceDescriptor.from(
475
+ (GRASS_BLADE_LIST_HEADER_WORDS + blade_capacity * GRASS_BLADE_RECORD_WORDS) * 4,
476
+ // read back for its count
477
+ GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
478
+ // the count, which the blades raise from zero
479
+ 0, GRASS_BLADE_LIST_HEADER_WORDS * 4,
480
+ ));
481
+
482
+ const args_data = {};
483
+
484
+ const args_pass = graph.add("make blade draw", args_data, (data, resources, context) => {
485
+ shader_grass_blade_draw_args.dispatch({
486
+ encoder: context.encoder,
487
+ bindings: {
488
+ settings,
489
+ grass_blades: resources.get(data.blades),
490
+ draw_args: resources.get(data.draw_args),
491
+ },
492
+ });
493
+ });
494
+
495
+ args_data.blades = args_pass.write(args_pass.read(expand_data.blades));
496
+ args_data.draw_args = args_pass.create("blade draw arguments", BufferResourceDescriptor.from(
497
+ 16,
498
+ GPUBufferUsage.STORAGE | GPUBufferUsage.INDIRECT,
499
+ ));
500
+
501
+ graph.pop_scope();
502
+
503
+ const product = new BladeProduct();
504
+
505
+ product.blades = args_data.blades;
506
+ product.draw_args = args_data.draw_args;
507
+
508
+ this.#products.set(view, product);
509
+
510
+ // how many blades asked for a place: a list too small for them is made larger from the next frame
511
+ graph_read_buffer({ graph, buffer: args_data.blades, offset: GRASS_BLADE_LIST_COUNT * 4, size: 4 })
512
+ .then(reference => {
513
+ try {
514
+ this.#blades_asked = Math.max(this.#blades_asked, new Uint32Array(reference.getValue())[0]);
515
+ } finally {
516
+ reference.release();
517
+ }
518
+ })
519
+ .catch(() => {
520
+ // a reading lost to a timeout or a lost device: a later frame's carries it
521
+ });
522
+ }
523
+
524
+ /**
525
+ * Record a view's blade draw: its blades into the blade id target under the scene's depth, then the
526
+ * G-buffer's surface, the visibility word and the velocity under every pixel a blade covers. Publishes
527
+ * the depth, the G-buffer targets, the visibility buffer and the velocity buffer it wrote. Records nothing for a view {@link graph_generate} made no blades for this frame.
528
+ *
529
+ * @param {FrameContext} frame at the phase where the G-buffer is written into
530
+ */
531
+ graph_draw(frame) {
532
+ const view = frame.view;
533
+ const product = this.#products.get(view);
534
+
535
+ if (product === undefined) {
536
+ return;
537
+ }
538
+
539
+ this.#products.delete(view);
540
+
541
+ const graph = frame.graph;
542
+ const scene = view.scene;
543
+ const camera = view.camera;
544
+
545
+ const view_textures = frame.get(ViewTextures);
546
+ const gbuffer = frame.get(GBufferTextures);
547
+
548
+ graph.push_scope("grass blades");
549
+
550
+ const id_data = {};
551
+
552
+ const id_pass = graph.add("draw blade ids", id_data, (data, resources, context) => {
553
+ const encoder = context.encoder;
554
+
555
+ const bindings = GRASS_BLADE_ID_RESOURCES.generateBindings({
556
+ camera: camera.gpu_buffer,
557
+ scene_database: scene.scene_database_buffer,
558
+ grass_blades: resources.get(data.blades),
559
+ }, encoder);
560
+
561
+ const pass = encoder.constructRenderPass({
562
+ label: "Grass Blade Ids",
563
+ pipeline: GRASS_BLADE_ID_PIPELINE,
564
+ bindings,
565
+ colorAttachments: [{
566
+ view: resources.get(data.ids).obtainView(MIP_0),
567
+ loadOp: "clear",
568
+ clearValue: [GRASS_BLADE_ID_NONE, 0, 0, 0],
569
+ storeOp: "store",
570
+ }],
571
+ depthStencilAttachment: {
572
+ view: resources.get(data.depth).obtainView(DEFAULT_DEPTH_TEXTURE_VIEW),
573
+ // the scene's depth is what blades are hidden by, and what they then hide
574
+ depthLoadOp: "load",
575
+ depthStoreOp: "store",
576
+ },
577
+ });
578
+
579
+ pass.drawIndirect(resources.get(data.draw_args), 0);
580
+ pass.end();
581
+ });
582
+
583
+ id_data.blades = id_pass.read(product.blades);
584
+ id_data.draw_args = id_pass.read(product.draw_args);
585
+ id_data.depth = id_pass.write(view_textures.depth);
586
+ id_data.ids = id_pass.create("blade ids", TextureResourceDescriptor.from({
587
+ format: GRASS_BLADE_ID_FORMAT,
588
+ resolution: frame.resolution,
589
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
590
+ }));
591
+
592
+ view_textures.depth = id_data.depth;
593
+
594
+ const resolve_data = {};
595
+
596
+ const inverse_view_projection = new Float32Array(16);
597
+ const view_projection_previous = new Float32Array(16);
598
+
599
+ view_velocity_matrices(view, inverse_view_projection, view_projection_previous);
600
+
601
+ const resolve_pass = graph.add("resolve blades", resolve_data, (data, resources, context) => {
602
+ const encoder = context.encoder;
603
+
604
+ const bindings = GRASS_BLADE_RESOLVE_RESOURCES.generateBindings({
605
+ camera: camera.gpu_buffer,
606
+ scene_database: scene.scene_database_buffer,
607
+ grass_blades: resources.get(data.blades),
608
+ grass_species: this.#species_buffer,
609
+ grass_ids: resources.get(data.ids).obtainView(MIP_0),
610
+ scene_depth: resources.get(data.depth).obtainView(DEFAULT_DEPTH_TEXTURE_VIEW),
611
+ inverse_view_projection: encoder.allocateTransientBufferAndLoad(inverse_view_projection.buffer, GPUBufferUsage.UNIFORM),
612
+ view_projection_previous: encoder.allocateTransientBufferAndLoad(view_projection_previous.buffer, GPUBufferUsage.UNIFORM),
613
+ }, encoder);
614
+
615
+ const attachment = handle => ({
616
+ view: resources.get(handle).obtainView(MIP_0),
617
+ // every pixel no blade covers keeps what the scene left there
618
+ loadOp: "load",
619
+ storeOp: "store",
620
+ });
621
+
622
+ const pass = encoder.constructRenderPass({
623
+ label: "Grass Blade Resolve",
624
+ pipeline: GRASS_BLADE_RESOLVE_PIPELINE,
625
+ bindings,
626
+ colorAttachments: [
627
+ attachment(data.pbr),
628
+ attachment(data.normal),
629
+ attachment(data.albedo),
630
+ attachment(data.emissive),
631
+ attachment(data.visibility),
632
+ attachment(data.velocity),
633
+ ],
634
+ });
635
+
636
+ pass.draw(3);
637
+ pass.end();
638
+ });
639
+
640
+ resolve_data.blades = resolve_pass.read(product.blades);
641
+ resolve_data.ids = resolve_pass.read(id_data.ids);
642
+ resolve_data.depth = resolve_pass.read(id_data.depth);
643
+
644
+ // in place: the written handles are what the record hands on
645
+ resolve_data.pbr = resolve_pass.write(gbuffer.pbr);
646
+ resolve_data.normal = resolve_pass.write(gbuffer.normal);
647
+ resolve_data.albedo = resolve_pass.write(gbuffer.albedo);
648
+ resolve_data.emissive = resolve_pass.write(gbuffer.emissive);
649
+
650
+ gbuffer.pbr = resolve_data.pbr;
651
+ gbuffer.normal = resolve_data.normal;
652
+ gbuffer.albedo = resolve_data.albedo;
653
+ gbuffer.emissive = resolve_data.emissive;
654
+
655
+ resolve_data.visibility = resolve_pass.write(view_textures.visibility);
656
+ resolve_data.velocity = resolve_pass.write(view_textures.velocity);
657
+
658
+ view_textures.visibility = resolve_data.visibility;
659
+ view_textures.velocity = resolve_data.velocity;
660
+
661
+ graph.pop_scope();
662
+ }
663
+
664
+ /**
665
+ * Let go of everything on the device. The species stay listed.
666
+ */
667
+ destroy() {
668
+ this.#species_buffer?.destroy();
669
+ this.#species_buffer = null;
670
+ this.#species_dirty = true;
671
+ this.#clock_buffer?.destroy();
672
+ this.#clock_buffer = null;
673
+ this.press.destroy();
674
+ this.#products.clear();
675
+ }
676
+ }