@woosh/meep-engine 3.64.1 → 3.67.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 (372) 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/format/lut/cube/CubeLut.d.ts +38 -0
  58. package/src/format/lut/cube/CubeLut.d.ts.map +1 -0
  59. package/src/format/lut/cube/CubeLut.js +23 -0
  60. package/src/format/lut/cube/cube_read.d.ts +23 -0
  61. package/src/format/lut/cube/cube_read.d.ts.map +1 -0
  62. package/src/format/lut/cube/cube_read.js +199 -0
  63. package/src/format/lut/cube/cube_write.d.ts +15 -0
  64. package/src/format/lut/cube/cube_write.d.ts.map +1 -0
  65. package/src/format/lut/cube/cube_write.js +90 -0
  66. package/src/shade/device/shader/ShaderModuleCompiler.d.ts +2 -0
  67. package/src/shade/device/shader/ShaderModuleCompiler.d.ts.map +1 -1
  68. package/src/shade/device/shader/ShaderModuleCompiler.js +25 -2
  69. package/src/shade/playground/grass_surfaces/index.html +75 -0
  70. package/src/shade/playground/grass_surfaces/main.d.ts +2 -0
  71. package/src/shade/playground/grass_surfaces/main.d.ts.map +1 -0
  72. package/src/shade/playground/grass_surfaces/main.js +593 -0
  73. package/src/shade/playground/grass_surfaces/read_grass_surfaces.d.ts +62 -0
  74. package/src/shade/playground/grass_surfaces/read_grass_surfaces.d.ts.map +1 -0
  75. package/src/shade/playground/grass_surfaces/read_grass_surfaces.js +188 -0
  76. package/src/shade/playground/probe_clipmap/README.md +1 -0
  77. package/src/shade/playground/probe_clipmap/index.html +5 -0
  78. package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -1
  79. package/src/shade/playground/probe_clipmap/main.js +7 -0
  80. package/src/shade/playground/probe_clipmap_box/README.md +5 -1
  81. package/src/shade/playground/probe_clipmap_box/index.html +12 -0
  82. package/src/shade/playground/probe_clipmap_box/main.d.ts.map +1 -1
  83. package/src/shade/playground/probe_clipmap_box/main.js +15 -0
  84. package/src/shade/playground/probe_clipmap_box/scene.d.ts +8 -1
  85. package/src/shade/playground/probe_clipmap_box/scene.d.ts.map +1 -1
  86. package/src/shade/playground/probe_clipmap_box/scene.js +74 -6
  87. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  88. package/src/shade/renderer/Renderer.js +59 -55
  89. package/src/shade/renderer/deferred/tonemap/ColorGrade.d.ts +73 -4
  90. package/src/shade/renderer/deferred/tonemap/ColorGrade.d.ts.map +1 -1
  91. package/src/shade/renderer/deferred/tonemap/ColorGrade.js +113 -7
  92. package/src/shade/renderer/deferred/tonemap/TONEMAP_PURKINJE_SHIFT.d.ts +12 -0
  93. package/src/shade/renderer/deferred/tonemap/TONEMAP_PURKINJE_SHIFT.d.ts.map +1 -0
  94. package/src/shade/renderer/deferred/tonemap/TONEMAP_PURKINJE_SHIFT.js +12 -0
  95. package/src/shade/renderer/deferred/tonemap/ToneMapper.d.ts +15 -1
  96. package/src/shade/renderer/deferred/tonemap/ToneMapper.d.ts.map +1 -1
  97. package/src/shade/renderer/deferred/tonemap/ToneMapper.js +31 -3
  98. package/src/shade/renderer/deferred/tonemap/chunk_tonemap_purkinje.d.ts +25 -0
  99. package/src/shade/renderer/deferred/tonemap/chunk_tonemap_purkinje.d.ts.map +1 -0
  100. package/src/shade/renderer/deferred/tonemap/chunk_tonemap_purkinje.js +51 -0
  101. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_lut.d.ts +2 -2
  102. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_lut.d.ts.map +1 -1
  103. package/src/shade/renderer/deferred/tonemap/shader_tonemap_HDR_lut.js +6 -3
  104. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_lut.d.ts +3 -2
  105. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_lut.d.ts.map +1 -1
  106. package/src/shade/renderer/deferred/tonemap/shader_tonemap_LDR_lut.js +7 -3
  107. package/src/shade/renderer/extension/ViewTextures.d.ts +12 -5
  108. package/src/shade/renderer/extension/ViewTextures.d.ts.map +1 -1
  109. package/src/shade/renderer/extension/ViewTextures.js +19 -5
  110. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +3 -1
  111. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts.map +1 -1
  112. package/src/shade/renderer/fluid/GPUFluidCascadeStack.js +6 -1
  113. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +7 -0
  114. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts.map +1 -1
  115. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.js +10 -0
  116. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +7 -1
  117. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  118. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +46 -15
  119. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.d.ts +3 -2
  120. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.d.ts.map +1 -1
  121. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.js +3 -2
  122. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.d.ts +22 -0
  123. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.d.ts.map +1 -0
  124. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.js +247 -0
  125. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +50 -0
  126. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  127. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +101 -0
  128. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts +2 -1
  129. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts.map +1 -1
  130. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.js +2 -1
  131. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts +8 -0
  132. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts.map +1 -1
  133. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.js +12 -0
  134. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts +12 -6
  135. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts.map +1 -1
  136. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.js +35 -29
  137. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_clipmap.d.ts.map +1 -1
  138. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_clipmap.js +4 -2
  139. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_material.d.ts.map +1 -1
  140. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_material.js +6 -4
  141. package/src/shade/renderer/global_illumination/probe_clipmap/material/GPUBrickMaterial.d.ts.map +1 -1
  142. package/src/shade/renderer/global_illumination/probe_clipmap/material/GPUBrickMaterial.js +2 -1
  143. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.d.ts +6 -5
  144. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.d.ts.map +1 -1
  145. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.js +15 -14
  146. package/src/shade/renderer/global_illumination/probe_clipmap/material/shader_brick_material_gather.d.ts.map +1 -1
  147. package/src/shade/renderer/global_illumination/probe_clipmap/material/shader_brick_material_gather.js +4 -2
  148. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +19 -2
  149. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  150. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +128 -10
  151. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +19 -1
  152. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  153. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +27 -2
  154. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts +19 -11
  155. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts.map +1 -1
  156. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.js +35 -11
  157. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  158. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +3 -1
  159. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.d.ts +40 -0
  160. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.d.ts.map +1 -0
  161. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.js +174 -0
  162. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_material.d.ts +4 -4
  163. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_material.js +10 -10
  164. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.d.ts +31 -0
  165. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.d.ts.map +1 -0
  166. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.js +54 -0
  167. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts +8 -4
  168. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
  169. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +10 -21
  170. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts +7 -2
  171. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts.map +1 -1
  172. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.js +33 -29
  173. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.d.ts +28 -0
  174. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.d.ts.map +1 -0
  175. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.js +138 -0
  176. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts +13 -9
  177. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts.map +1 -1
  178. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js +18 -11
  179. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.js +1 -1
  180. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.d.ts.map +1 -1
  181. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js +4 -2
  182. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts.map +1 -1
  183. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js +2 -3
  184. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts +5 -3
  185. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts.map +1 -1
  186. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js +15 -30
  187. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -1
  188. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
  189. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +4 -2
  190. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts +11 -0
  191. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts.map +1 -1
  192. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.js +29 -2
  193. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.d.ts +40 -0
  194. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.d.ts.map +1 -0
  195. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.js +126 -0
  196. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.d.ts +36 -0
  197. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.d.ts.map +1 -0
  198. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.js +221 -0
  199. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.d.ts +40 -0
  200. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.d.ts.map +1 -0
  201. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.js +86 -0
  202. package/src/shade/renderer/grass/blade/GPUGrassBlades.d.ts +135 -0
  203. package/src/shade/renderer/grass/blade/GPUGrassBlades.d.ts.map +1 -0
  204. package/src/shade/renderer/grass/blade/GPUGrassBlades.js +676 -0
  205. package/src/shade/renderer/grass/blade/GRASS_BLADE.d.ts +145 -0
  206. package/src/shade/renderer/grass/blade/GRASS_BLADE.d.ts.map +1 -0
  207. package/src/shade/renderer/grass/blade/GRASS_BLADE.js +179 -0
  208. package/src/shade/renderer/grass/blade/chunk_grass_blade.d.ts +63 -0
  209. package/src/shade/renderer/grass/blade/chunk_grass_blade.d.ts.map +1 -0
  210. package/src/shade/renderer/grass/blade/chunk_grass_blade.js +244 -0
  211. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.d.ts +58 -0
  212. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.d.ts.map +1 -0
  213. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.js +174 -0
  214. package/src/shade/renderer/grass/blade/grass_blade_id_draw.d.ts +25 -0
  215. package/src/shade/renderer/grass/blade/grass_blade_id_draw.d.ts.map +1 -0
  216. package/src/shade/renderer/grass/blade/grass_blade_id_draw.js +133 -0
  217. package/src/shade/renderer/grass/blade/grass_blade_mechanics.d.ts +80 -0
  218. package/src/shade/renderer/grass/blade/grass_blade_mechanics.d.ts.map +1 -0
  219. package/src/shade/renderer/grass/blade/grass_blade_mechanics.js +92 -0
  220. package/src/shade/renderer/grass/blade/grass_blade_resolve.d.ts +29 -0
  221. package/src/shade/renderer/grass/blade/grass_blade_resolve.d.ts.map +1 -0
  222. package/src/shade/renderer/grass/blade/grass_blade_resolve.js +175 -0
  223. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.d.ts +14 -0
  224. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.d.ts.map +1 -0
  225. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.js +45 -0
  226. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.d.ts +61 -0
  227. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.d.ts.map +1 -0
  228. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.js +340 -0
  229. package/src/shade/renderer/grass/blade/shader_grass_cell_count.d.ts +46 -0
  230. package/src/shade/renderer/grass/blade/shader_grass_cell_count.d.ts.map +1 -0
  231. package/src/shade/renderer/grass/blade/shader_grass_cell_count.js +280 -0
  232. package/src/shade/renderer/grass/population/chunk_grass_population.d.ts +60 -0
  233. package/src/shade/renderer/grass/population/chunk_grass_population.d.ts.map +1 -0
  234. package/src/shade/renderer/grass/population/chunk_grass_population.js +171 -0
  235. package/src/shade/renderer/grass/press/GPUGrassPress.d.ts +99 -0
  236. package/src/shade/renderer/grass/press/GPUGrassPress.d.ts.map +1 -0
  237. package/src/shade/renderer/grass/press/GPUGrassPress.js +436 -0
  238. package/src/shade/renderer/grass/press/GRASS_PRESS.d.ts +179 -0
  239. package/src/shade/renderer/grass/press/GRASS_PRESS.d.ts.map +1 -0
  240. package/src/shade/renderer/grass/press/GRASS_PRESS.js +217 -0
  241. package/src/shade/renderer/grass/press/chunk_grass_press.d.ts +65 -0
  242. package/src/shade/renderer/grass/press/chunk_grass_press.d.ts.map +1 -0
  243. package/src/shade/renderer/grass/press/chunk_grass_press.js +296 -0
  244. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts +31 -0
  245. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts.map +1 -0
  246. package/src/shade/renderer/grass/press/shader_grass_press_mark.js +169 -0
  247. package/src/shade/renderer/grass/press/shader_grass_press_stamp.d.ts +27 -0
  248. package/src/shade/renderer/grass/press/shader_grass_press_stamp.d.ts.map +1 -0
  249. package/src/shade/renderer/grass/press/shader_grass_press_stamp.js +183 -0
  250. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.d.ts +193 -0
  251. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.d.ts.map +1 -0
  252. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.js +1253 -0
  253. package/src/shade/renderer/grass/surface/GRASS_SURFACE.d.ts +211 -0
  254. package/src/shade/renderer/grass/surface/GRASS_SURFACE.d.ts.map +1 -0
  255. package/src/shade/renderer/grass/surface/GRASS_SURFACE.js +241 -0
  256. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.d.ts +82 -0
  257. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.d.ts.map +1 -0
  258. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.js +111 -0
  259. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.d.ts +39 -0
  260. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.d.ts.map +1 -0
  261. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.js +85 -0
  262. package/src/shade/renderer/grass/surface/chunk_grass_directory.d.ts +29 -0
  263. package/src/shade/renderer/grass/surface/chunk_grass_directory.d.ts.map +1 -0
  264. package/src/shade/renderer/grass/surface/chunk_grass_directory.js +112 -0
  265. package/src/shade/renderer/grass/surface/chunk_grass_slot.d.ts +27 -0
  266. package/src/shade/renderer/grass/surface/chunk_grass_slot.d.ts.map +1 -0
  267. package/src/shade/renderer/grass/surface/chunk_grass_slot.js +50 -0
  268. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.d.ts +21 -0
  269. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.d.ts.map +1 -0
  270. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.js +41 -0
  271. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.d.ts +32 -0
  272. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.d.ts.map +1 -0
  273. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.js +136 -0
  274. package/src/shade/renderer/grass/surface/chunk_grass_surfel.d.ts +37 -0
  275. package/src/shade/renderer/grass/surface/chunk_grass_surfel.d.ts.map +1 -0
  276. package/src/shade/renderer/grass/surface/chunk_grass_surfel.js +85 -0
  277. package/src/shade/renderer/grass/surface/chunk_grass_tile.d.ts +25 -0
  278. package/src/shade/renderer/grass/surface/chunk_grass_tile.d.ts.map +1 -0
  279. package/src/shade/renderer/grass/surface/chunk_grass_tile.js +52 -0
  280. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.d.ts +23 -0
  281. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.d.ts.map +1 -0
  282. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.js +87 -0
  283. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.d.ts +43 -0
  284. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.d.ts.map +1 -0
  285. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.js +265 -0
  286. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.d.ts +13 -0
  287. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.d.ts.map +1 -0
  288. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.js +49 -0
  289. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.d.ts +62 -0
  290. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.d.ts.map +1 -0
  291. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.js +162 -0
  292. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.d.ts +40 -0
  293. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.d.ts.map +1 -0
  294. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.js +155 -0
  295. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.d.ts +19 -0
  296. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.d.ts.map +1 -0
  297. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.js +58 -0
  298. package/src/shade/renderer/grass/surface/shader_grass_surface_want.d.ts +30 -0
  299. package/src/shade/renderer/grass/surface/shader_grass_surface_want.d.ts.map +1 -0
  300. package/src/shade/renderer/grass/surface/shader_grass_surface_want.js +251 -0
  301. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.d.ts +21 -0
  302. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.d.ts.map +1 -0
  303. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.js +75 -0
  304. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts +35 -9
  305. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
  306. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +81 -11
  307. package/src/shade/renderer/postprocess/eye/shader_autoexposure_adapt.d.ts.map +1 -1
  308. package/src/shade/renderer/postprocess/eye/shader_autoexposure_adapt.js +4 -1
  309. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts.map +1 -1
  310. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.js +4 -23
  311. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.d.ts +12 -0
  312. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.d.ts.map +1 -0
  313. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.js +29 -0
  314. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
  315. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +22 -0
  316. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  317. package/src/shade/renderer/scene/GPUSceneContext.js +3 -0
  318. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.d.ts +27 -0
  319. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.d.ts.map +1 -0
  320. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.js +38 -0
  321. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.d.ts +28 -0
  322. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.d.ts.map +1 -0
  323. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.js +58 -0
  324. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.d.ts.map +1 -1
  325. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.js +8 -0
  326. package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.d.ts +6 -0
  327. package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.d.ts.map +1 -1
  328. package/src/shade/renderer/shader/chunk/color/conversion/chunk_CRM_REC709_AP1.js +7 -0
  329. package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.d.ts +4 -4
  330. package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.d.ts.map +1 -1
  331. package/src/shade/renderer/shader/chunk/color/grade/chunk_color_grade.js +86 -5
  332. package/src/shade/renderer/shader/chunk/color/tonemap/purkinje/chunk_apply_purkinje_shift.d.ts +65 -0
  333. package/src/shade/renderer/shader/chunk/color/tonemap/purkinje/chunk_apply_purkinje_shift.d.ts.map +1 -0
  334. package/src/shade/renderer/shader/chunk/color/tonemap/purkinje/chunk_apply_purkinje_shift.js +136 -0
  335. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.d.ts +37 -0
  336. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.d.ts.map +1 -0
  337. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.js +148 -0
  338. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.d.ts +20 -0
  339. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.d.ts.map +1 -0
  340. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.js +169 -0
  341. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.d.ts +18 -0
  342. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.d.ts.map +1 -1
  343. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.js +28 -0
  344. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.d.ts +13 -0
  345. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.d.ts.map +1 -0
  346. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.js +22 -0
  347. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  348. package/src/shade/renderer/water/GPUWaterRenderer.js +4 -0
  349. package/src/shade/renderer/wind/GPUSceneWind.d.ts +52 -5
  350. package/src/shade/renderer/wind/GPUSceneWind.d.ts.map +1 -1
  351. package/src/shade/renderer/wind/GPUSceneWind.js +164 -8
  352. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.d.ts +3 -1
  353. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.d.ts.map +1 -1
  354. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.js +3 -1
  355. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts +2 -1
  356. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts.map +1 -1
  357. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.js +18 -13
  358. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.d.ts +13 -0
  359. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.d.ts.map +1 -0
  360. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.js +23 -0
  361. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.d.ts +1 -0
  362. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.d.ts.map +1 -1
  363. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.js +6 -1
  364. package/src/shade/renderer/wind/wind_field_add_resources.d.ts +11 -0
  365. package/src/shade/renderer/wind/wind_field_add_resources.d.ts.map +1 -1
  366. package/src/shade/renderer/wind/wind_field_add_resources.js +15 -0
  367. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +1 -1
  368. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  369. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +2 -0
  370. package/src/shade/renderer/shader/chunk/color/tonemap/purkinjie/chunk_apply_purkinjie_shift.d.ts +0 -11
  371. package/src/shade/renderer/shader/chunk/color/tonemap/purkinjie/chunk_apply_purkinjie_shift.d.ts.map +0 -1
  372. package/src/shade/renderer/shader/chunk/color/tonemap/purkinjie/chunk_apply_purkinjie_shift.js +0 -56
@@ -1,5 +1,6 @@
1
1
  import { chunk_quat_rotate_v3 } from "../../../../shade/renderer/shader/chunk/geometry/quaternion/chunk_v3_apply_quat.js";
2
2
  import { chunk_rigid_velocity_at_point } from "../../../../shade/renderer/shader/chunk/physics/kinematics/chunk_rigid_velocity_at_point.js";
3
+ import { chunk_shape_record_line_span } from "../../../../shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.js";
3
4
  import { chunk_shape_record_signed_distance } from "../../../../shade/renderer/shader/chunk/sdf/chunk_shape_record_signed_distance.js";
4
5
  import { CodeChunk } from "../../../../shade/renderer/shader/compiler/CodeChunk.js";
5
6
  import { FLUID_OBSTACLE_RECORD_STRUCT } from "./FLUID_OBSTACLE_RECORD_STRUCT.js";
@@ -10,7 +11,11 @@ import { FLUID_OBSTACLE_RECORD_STRUCT } from "./FLUID_OBSTACLE_RECORD_STRUCT.js"
10
11
  * - `fluid_obstacle_record_signed_distance(record, global, x) -> f32`: signed distance to its
11
12
  * surface, negative inside; the point is solid when it is at most `record.inflation`;
12
13
  * - `fluid_obstacle_record_wall_velocity(record, global, x) -> vec3<f32>`: the wall's velocity there,
13
- * `rigid_velocity_at_point(v, ω, t, x)` with `t` the node's translation.
14
+ * `rigid_velocity_at_point(v, ω, t, x)` with `t` the node's translation;
15
+ * - `fluid_obstacle_record_line_span(record, global, origin, direction) -> vec2<f32>`: the part of the
16
+ * world line `origin + t · direction` (`direction` unit) inside its surface, as the `t` it enters at
17
+ * and the `t` it leaves at, the first greater than the second for a line that misses
18
+ * (`shape_record_line_span`). The inflation is not part of it.
14
19
  *
15
20
  * The node poses the record rigidly: its translation, and its matrix's rotation with each column
16
21
  * normalised, scale ignored, as the physics narrowphase and the CPU fluid pose a collider; then the
@@ -47,6 +52,26 @@ fn fluid_obstacle_record_signed_distance(
47
52
  return shape_record_signed_distance(record.shape_kind, record.shape_parameters, local);
48
53
  }
49
54
 
55
+ fn fluid_obstacle_record_line_span(
56
+ record: ${FLUID_OBSTACLE_RECORD_STRUCT.wgsl_ref}, global: mat4x4<f32>, origin: vec3<f32>, direction: vec3<f32>
57
+ ) -> vec2<f32> {
58
+ // the node's rotation: its columns normalised, so its scale is ignored
59
+ let r0 = global[0].xyz * (1.0 / length(global[0].xyz));
60
+ let r1 = global[1].xyz * (1.0 / length(global[1].xyz));
61
+ let r2 = global[2].xyz * (1.0 / length(global[2].xyz));
62
+
63
+ let offset = origin - global[3].xyz;
64
+
65
+ // the record's own pose within the collider, inverted
66
+ let q = record.pose_rotation;
67
+ let inverse = vec4<f32>(-q.xyz, q.w);
68
+
69
+ let local_origin = quat_rotate_v3(inverse, vec3<f32>(dot(r0, offset), dot(r1, offset), dot(r2, offset)) - record.pose_translation);
70
+ let local_direction = quat_rotate_v3(inverse, vec3<f32>(dot(r0, direction), dot(r1, direction), dot(r2, direction)));
71
+
72
+ return shape_record_line_span(record.shape_kind, record.shape_parameters, local_origin, local_direction);
73
+ }
74
+
50
75
  fn fluid_obstacle_record_wall_velocity(
51
76
  record: ${FLUID_OBSTACLE_RECORD_STRUCT.wgsl_ref}, global: mat4x4<f32>, x: vec3<f32>
52
77
  ) -> vec3<f32> {
@@ -57,5 +82,6 @@ fn fluid_obstacle_record_wall_velocity(
57
82
  chunk_quat_rotate_v3,
58
83
  chunk_rigid_velocity_at_point,
59
84
  chunk_shape_record_signed_distance,
85
+ chunk_shape_record_line_span,
60
86
  ]
61
87
  );
@@ -0,0 +1,38 @@
1
+ /**
2
+ * A 3D lookup table as a `.cube` file holds it — what {@link cube_read } returns and {@link cube_write } takes.
3
+ *
4
+ * Entry `r + g·size + b·size²` holds the output for the input at lattice point (r, g, b): the input whose channel c
5
+ * is `domain_min[c] + (domain_max[c] - domain_min[c]) · i / (size - 1)` for that channel's index i. Red runs
6
+ * fastest, then green, then blue, as the format lays the entries out.
7
+ *
8
+ * The format carries numbers only. What the input and output mean — their primaries, transfer curves and units — is
9
+ * a contract between the writer and the reader, stated outside the table; a `.cube` file conventionally says it in
10
+ * its comments.
11
+ */
12
+ type CubeLut = {
13
+ /**
14
+ * the `TITLE`, `""` when the file has none
15
+ */
16
+ title: string;
17
+ /**
18
+ * the comment lines in file order, each without its `#` and the space after it
19
+ */
20
+ comments: string[];
21
+ /**
22
+ * entries along each edge, at least 2
23
+ */
24
+ size: number;
25
+ /**
26
+ * the input at lattice index 0, per channel
27
+ */
28
+ domain_min: number[];
29
+ /**
30
+ * the input at lattice index `size - 1`, per channel
31
+ */
32
+ domain_max: number[];
33
+ /**
34
+ * `size³` RGB triples
35
+ */
36
+ data: Float32Array;
37
+ };
38
+ //# sourceMappingURL=CubeLut.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CubeLut.d.ts","sourceRoot":"","sources":["../../../../../src/format/lut/cube/CubeLut.js"],"names":[],"mappings":";;;;;;;;;;;;;;;WAYc,MAAM;;;;cACN,MAAM,EAAE;;;;UACR,MAAM;;;;gBACN,MAAM,EAAE;;;;gBACR,MAAM,EAAE;;;;UACR,YAAY"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * A 3D lookup table as a `.cube` file holds it — what {@link cube_read} returns and {@link cube_write} takes.
3
+ *
4
+ * Entry `r + g·size + b·size²` holds the output for the input at lattice point (r, g, b): the input whose channel c
5
+ * is `domain_min[c] + (domain_max[c] - domain_min[c]) · i / (size - 1)` for that channel's index i. Red runs
6
+ * fastest, then green, then blue, as the format lays the entries out.
7
+ *
8
+ * The format carries numbers only. What the input and output mean — their primaries, transfer curves and units — is
9
+ * a contract between the writer and the reader, stated outside the table; a `.cube` file conventionally says it in
10
+ * its comments.
11
+ *
12
+ * @typedef {object} CubeLut
13
+ * @property {string} title the `TITLE`, `""` when the file has none
14
+ * @property {string[]} comments the comment lines in file order, each without its `#` and the space after it
15
+ * @property {number} size entries along each edge, at least 2
16
+ * @property {number[]} domain_min the input at lattice index 0, per channel
17
+ * @property {number[]} domain_max the input at lattice index `size - 1`, per channel
18
+ * @property {Float32Array} data `size³` RGB triples
19
+ *
20
+ * @see Adobe Systems, "Cube LUT Specification", version 1.0, 2013
21
+ * @author Alex Goldring
22
+ * @copyright Company Named Limited (c) 2026
23
+ */
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Read a 3D LUT in the `.cube` format.
3
+ *
4
+ * **What it reads**: `TITLE`, `LUT_3D_SIZE`, `DOMAIN_MIN`, `DOMAIN_MAX` and comment lines, in any order ahead of the
5
+ * table, then the table: one entry per line, three decimal numbers apart by spaces or tabs, red fastest. Blank lines
6
+ * are skipped anywhere and comments are kept wherever they are. `DOMAIN_MIN` and `DOMAIN_MAX` default to 0 and 1,
7
+ * as the format defines.
8
+ *
9
+ * **What it refuses**, by name: a 1D LUT (`LUT_1D_SIZE`), any other keyword, a keyword after the table has begun, a
10
+ * size under 2, a table with more or fewer than `size³` entries, an entry that is not three decimal numbers, and a
11
+ * domain whose minimum is not under its maximum in every channel. A size is checked against what the text could hold
12
+ * before anything is allocated for the table, so a file cannot claim more entries than its own length allows.
13
+ *
14
+ * @param {string} text the whole file
15
+ * @returns {CubeLut}
16
+ * @throws {Error} naming the line and what is wrong with it
17
+ *
18
+ * @see cube_write
19
+ * @author Alex Goldring
20
+ * @copyright Company Named Limited (c) 2026
21
+ */
22
+ export function cube_read(text: string): CubeLut;
23
+ //# sourceMappingURL=cube_read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cube_read.d.ts","sourceRoot":"","sources":["../../../../../src/format/lut/cube/cube_read.js"],"names":[],"mappings":"AAqCA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,gCARW,MAAM,GACJ,OAAO,CAmJnB"}
@@ -0,0 +1,199 @@
1
+ /**
2
+ * A decimal number as a `.cube` file writes one: optional sign, digits with an optional point, optional exponent.
3
+ * Narrower than `Number()`, which also takes hexadecimal, `Infinity` and the empty string.
4
+ * @type {RegExp}
5
+ */
6
+ const DECIMAL = /^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/;
7
+
8
+ /**
9
+ * @param {string} token
10
+ * @param {number} line_number
11
+ * @returns {number}
12
+ */
13
+ function parse_number(token, line_number) {
14
+ if (!DECIMAL.test(token)) {
15
+ throw new Error(`CUBE: line ${line_number}: '${token}' is not a number`);
16
+ }
17
+
18
+ return Number(token);
19
+ }
20
+
21
+ /**
22
+ * @param {string[]} tokens the keyword and its three values
23
+ * @param {number} line_number
24
+ * @returns {number[]}
25
+ */
26
+ function parse_triple(tokens, line_number) {
27
+ if (tokens.length !== 4) {
28
+ throw new Error(`CUBE: line ${line_number}: ${tokens[0]} takes three numbers, found ${tokens.length - 1}`);
29
+ }
30
+
31
+ return [
32
+ parse_number(tokens[1], line_number),
33
+ parse_number(tokens[2], line_number),
34
+ parse_number(tokens[3], line_number),
35
+ ];
36
+ }
37
+
38
+ /**
39
+ * Read a 3D LUT in the `.cube` format.
40
+ *
41
+ * **What it reads**: `TITLE`, `LUT_3D_SIZE`, `DOMAIN_MIN`, `DOMAIN_MAX` and comment lines, in any order ahead of the
42
+ * table, then the table: one entry per line, three decimal numbers apart by spaces or tabs, red fastest. Blank lines
43
+ * are skipped anywhere and comments are kept wherever they are. `DOMAIN_MIN` and `DOMAIN_MAX` default to 0 and 1,
44
+ * as the format defines.
45
+ *
46
+ * **What it refuses**, by name: a 1D LUT (`LUT_1D_SIZE`), any other keyword, a keyword after the table has begun, a
47
+ * size under 2, a table with more or fewer than `size³` entries, an entry that is not three decimal numbers, and a
48
+ * domain whose minimum is not under its maximum in every channel. A size is checked against what the text could hold
49
+ * before anything is allocated for the table, so a file cannot claim more entries than its own length allows.
50
+ *
51
+ * @param {string} text the whole file
52
+ * @returns {CubeLut}
53
+ * @throws {Error} naming the line and what is wrong with it
54
+ *
55
+ * @see cube_write
56
+ * @author Alex Goldring
57
+ * @copyright Company Named Limited (c) 2026
58
+ */
59
+ export function cube_read(text) {
60
+ const lines = text.split(/\r\n|\n|\r/);
61
+ const line_count = lines.length;
62
+
63
+ let title = "";
64
+ const comments = [];
65
+ let size = 0;
66
+ const domain_min = [0, 0, 0];
67
+ const domain_max = [1, 1, 1];
68
+
69
+ /**
70
+ * @type {Float32Array|null}
71
+ */
72
+ let data = null;
73
+ let entries = 0;
74
+ let entry_count = 0;
75
+
76
+ for (let i = 0; i < line_count; i++) {
77
+ const line_number = i + 1;
78
+ const line = lines[i].trim();
79
+
80
+ if (line.length === 0) {
81
+ continue;
82
+ }
83
+
84
+ if (line.charCodeAt(0) === 35 /* # */) {
85
+ // the text after `# ` as it stands, trailing spaces and all
86
+ comments.push(lines[i].trimStart().substring(1).replace(/^ /, ""));
87
+ continue;
88
+ }
89
+
90
+ const tokens = line.split(/[ \t]+/);
91
+ const head = tokens[0];
92
+
93
+ if (/^[A-Za-z_]/.test(head)) {
94
+ if (entries > 0) {
95
+ throw new Error(`CUBE: line ${line_number}: keyword ${head} after the table has begun`);
96
+ }
97
+
98
+ switch (head) {
99
+ case "TITLE": {
100
+ const match = /^TITLE[ \t]+"([^"]*)"$/.exec(line);
101
+
102
+ if (match === null) {
103
+ throw new Error(`CUBE: line ${line_number}: TITLE takes one quoted string`);
104
+ }
105
+
106
+ title = match[1];
107
+ break;
108
+ }
109
+
110
+ case "LUT_3D_SIZE": {
111
+ if (tokens.length !== 2 || !/^\d+$/.test(tokens[1])) {
112
+ throw new Error(`CUBE: line ${line_number}: LUT_3D_SIZE takes one whole number`);
113
+ }
114
+
115
+ size = Number(tokens[1]);
116
+
117
+ if (size < 2) {
118
+ throw new Error(`CUBE: line ${line_number}: LUT_3D_SIZE is ${size}, under the format's 2`);
119
+ }
120
+
121
+ break;
122
+ }
123
+
124
+ case "DOMAIN_MIN": {
125
+ const values = parse_triple(tokens, line_number);
126
+ domain_min[0] = values[0];
127
+ domain_min[1] = values[1];
128
+ domain_min[2] = values[2];
129
+ break;
130
+ }
131
+
132
+ case "DOMAIN_MAX": {
133
+ const values = parse_triple(tokens, line_number);
134
+ domain_max[0] = values[0];
135
+ domain_max[1] = values[1];
136
+ domain_max[2] = values[2];
137
+ break;
138
+ }
139
+
140
+ case "LUT_1D_SIZE":
141
+ throw new Error(`CUBE: line ${line_number}: a 1D LUT, where a 3D LUT was expected`);
142
+
143
+ default:
144
+ throw new Error(`CUBE: line ${line_number}: unsupported keyword ${head}`);
145
+ }
146
+
147
+ continue;
148
+ }
149
+
150
+ // the table
151
+ if (data === null) {
152
+ if (size === 0) {
153
+ throw new Error(`CUBE: line ${line_number}: table entry before LUT_3D_SIZE`);
154
+ }
155
+
156
+ entry_count = size * size * size;
157
+
158
+ // every entry is at least three one-digit numbers and two separators, five characters, and each but the
159
+ // last ends its line
160
+ if (entry_count * 6 - 1 > text.length) {
161
+ throw new Error(`CUBE: LUT_3D_SIZE ${size} needs ${entry_count} entries, more than a file of ${text.length} characters can hold`);
162
+ }
163
+
164
+ data = new Float32Array(entry_count * 3);
165
+ }
166
+
167
+ if (tokens.length !== 3) {
168
+ throw new Error(`CUBE: line ${line_number}: an entry is three numbers, found ${tokens.length}`);
169
+ }
170
+
171
+ if (entries >= entry_count) {
172
+ throw new Error(`CUBE: line ${line_number}: more than the ${entry_count} entries of LUT_3D_SIZE ${size}`);
173
+ }
174
+
175
+ const at = entries * 3;
176
+
177
+ data[at] = parse_number(tokens[0], line_number);
178
+ data[at + 1] = parse_number(tokens[1], line_number);
179
+ data[at + 2] = parse_number(tokens[2], line_number);
180
+
181
+ entries++;
182
+ }
183
+
184
+ if (size === 0) {
185
+ throw new Error("CUBE: no LUT_3D_SIZE");
186
+ }
187
+
188
+ if (entries !== size * size * size) {
189
+ throw new Error(`CUBE: ${entries} entries, where LUT_3D_SIZE ${size} needs ${size * size * size}`);
190
+ }
191
+
192
+ for (let c = 0; c < 3; c++) {
193
+ if (!(domain_min[c] < domain_max[c])) {
194
+ throw new Error(`CUBE: the domain of channel ${c} runs from ${domain_min[c]} to ${domain_max[c]}`);
195
+ }
196
+ }
197
+
198
+ return { title, comments, size, domain_min, domain_max, data };
199
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Write a 3D LUT in the `.cube` format: the comments, `TITLE` where there is one, `LUT_3D_SIZE`, `DOMAIN_MIN`,
3
+ * `DOMAIN_MAX`, then one entry per line, red fastest. Each number is the shortest decimal that reads back as the same
4
+ * 32-bit float, so {@link cube_read} returns exactly the values written.
5
+ *
6
+ * @param {CubeLut} lut
7
+ * @returns {string} the file, lines ending in `\n`
8
+ * @throws {Error} where a value is not finite, or the title or a comment cannot be written on one line
9
+ *
10
+ * @see cube_read
11
+ * @author Alex Goldring
12
+ * @copyright Company Named Limited (c) 2026
13
+ */
14
+ export function cube_write({ title, comments, size, domain_min, domain_max, data }: CubeLut): string;
15
+ //# sourceMappingURL=cube_write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cube_write.d.ts","sourceRoot":"","sources":["../../../../../src/format/lut/cube/cube_write.js"],"names":[],"mappings":"AA6BA;;;;;;;;;;;;GAYG;AACH,oFARW,OAAO,GACL,MAAM,CAsDlB"}
@@ -0,0 +1,90 @@
1
+ import { assert } from "../../../core/assert.js";
2
+
3
+ /**
4
+ * The shortest decimal that reads back as the same 32-bit float.
5
+ *
6
+ * @param {number} value a float32 value, finite
7
+ * @returns {string}
8
+ */
9
+ function format_f32(value) {
10
+ for (let precision = 1; precision < 9; precision++) {
11
+ const text = value.toPrecision(precision);
12
+
13
+ if (Math.fround(Number(text)) === value) {
14
+ return text;
15
+ }
16
+ }
17
+
18
+ // nine significant digits always identify a float32
19
+ return value.toPrecision(9);
20
+ }
21
+
22
+ /**
23
+ * @param {number[]} triple
24
+ * @returns {string}
25
+ */
26
+ function format_triple(triple) {
27
+ return `${format_f32(Math.fround(triple[0]))} ${format_f32(Math.fround(triple[1]))} ${format_f32(Math.fround(triple[2]))}`;
28
+ }
29
+
30
+ /**
31
+ * Write a 3D LUT in the `.cube` format: the comments, `TITLE` where there is one, `LUT_3D_SIZE`, `DOMAIN_MIN`,
32
+ * `DOMAIN_MAX`, then one entry per line, red fastest. Each number is the shortest decimal that reads back as the same
33
+ * 32-bit float, so {@link cube_read} returns exactly the values written.
34
+ *
35
+ * @param {CubeLut} lut
36
+ * @returns {string} the file, lines ending in `\n`
37
+ * @throws {Error} where a value is not finite, or the title or a comment cannot be written on one line
38
+ *
39
+ * @see cube_read
40
+ * @author Alex Goldring
41
+ * @copyright Company Named Limited (c) 2026
42
+ */
43
+ export function cube_write({ title, comments, size, domain_min, domain_max, data }) {
44
+ assert.isString(title, 'title');
45
+ assert.isArray(comments, 'comments');
46
+ assert.isNonNegativeInteger(size, 'size');
47
+ assert.greaterThanOrEqual(size, 2, 'size');
48
+ assert.isInstanceOf(data, Float32Array, 'data', 'Float32Array');
49
+ assert.equal(data.length, size * size * size * 3, 'data.length !== size³ × 3');
50
+
51
+ if (/["\r\n]/.test(title)) {
52
+ throw new Error(`CUBE: a title cannot hold a quote or a line break, '${title}'`);
53
+ }
54
+
55
+ const lines = [];
56
+
57
+ for (const comment of comments) {
58
+ assert.isString(comment, 'comment');
59
+
60
+ if (/[\r\n]/.test(comment)) {
61
+ throw new Error(`CUBE: a comment cannot hold a line break, '${comment}'`);
62
+ }
63
+
64
+ lines.push(`# ${comment}`);
65
+ }
66
+
67
+ if (title.length > 0) {
68
+ lines.push(`TITLE "${title}"`);
69
+ }
70
+
71
+ lines.push(`LUT_3D_SIZE ${size}`);
72
+ lines.push(`DOMAIN_MIN ${format_triple(domain_min)}`);
73
+ lines.push(`DOMAIN_MAX ${format_triple(domain_max)}`);
74
+
75
+ const value_count = data.length;
76
+
77
+ for (let i = 0; i < value_count; i++) {
78
+ if (!Number.isFinite(data[i])) {
79
+ throw new Error(`CUBE: entry ${Math.floor(i / 3)} holds ${data[i]}, which the format cannot write`);
80
+ }
81
+ }
82
+
83
+ for (let i = 0; i < value_count; i += 3) {
84
+ lines.push(`${format_f32(data[i])} ${format_f32(data[i + 1])} ${format_f32(data[i + 2])}`);
85
+ }
86
+
87
+ lines.push("");
88
+
89
+ return lines.join("\n");
90
+ }
@@ -8,6 +8,8 @@ export class ShaderModuleCompiler {
8
8
  */
9
9
  constructor(device: GPUDevice);
10
10
  /**
11
+ * The module for `descriptor`. Equal descriptors are handed the same module for as long as
12
+ * something holds it; once nothing does, a later call may compile it again and hand out a new one.
11
13
  *
12
14
  * @param {ShaderModuleDescriptor} descriptor
13
15
  * @returns {GPUShaderModule}
@@ -1 +1 @@
1
- {"version":3,"file":"ShaderModuleCompiler.d.ts","sourceRoot":"","sources":["../../../../../src/shade/device/shader/ShaderModuleCompiler.js"],"names":[],"mappings":"AAGA;;GAEG;AAEH;IAaI;;;OAGG;IACH,+BAEC;IAwCD;;;;OAIG;IACH,mBAHW,sBAAsB,mBAOhC;;CAEJ;qCAzEY,OAAO,qDAAqD,EAAE,sBAAsB"}
1
+ {"version":3,"file":"ShaderModuleCompiler.d.ts","sourceRoot":"","sources":["../../../../../src/shade/device/shader/ShaderModuleCompiler.js"],"names":[],"mappings":"AAGA;;GAEG;AAEH;IAmBI;;;OAGG;IACH,+BAEC;IAwCD;;;;;;OAMG;IACH,mBAHW,sBAAsB,mBAsBhC;;CAEJ;qCAhGY,OAAO,qDAAqD,EAAE,sBAAsB"}
@@ -13,8 +13,14 @@ export class ShaderModuleCompiler {
13
13
  #device
14
14
 
15
15
  /**
16
+ * Held weakly. A pipeline keeps the module it was built from alive in the GPU process without our
17
+ * help, while the browser charges every `GPUShaderModule` object the page still references to the
18
+ * JS heap's accounting as external memory, and the garbage a collection is allowed to gather grows
19
+ * with that. So a module is kept only for as long as something holds it: one nobody holds goes at
20
+ * the next major collection, and a later request compiles it again from the descriptor, which this
21
+ * map does keep.
16
22
  *
17
- * @type {HashMap<ShaderModuleDescriptor, GPUShaderModule>}
23
+ * @type {HashMap<ShaderModuleDescriptor, WeakRef<GPUShaderModule>>}
18
24
  */
19
25
  #cache = new HashMap();
20
26
 
@@ -65,14 +71,31 @@ export class ShaderModuleCompiler {
65
71
  }
66
72
 
67
73
  /**
74
+ * The module for `descriptor`. Equal descriptors are handed the same module for as long as
75
+ * something holds it; once nothing does, a later call may compile it again and hand out a new one.
68
76
  *
69
77
  * @param {ShaderModuleDescriptor} descriptor
70
78
  * @returns {GPUShaderModule}
71
79
  */
72
80
  obtain(descriptor) {
81
+ const cache = this.#cache;
73
82
 
74
- return this.#cache.getOrCompute(descriptor, this.#compile, this);
83
+ const held = cache.get(descriptor);
75
84
 
85
+ if (held !== undefined) {
86
+ const live = held.deref();
87
+
88
+ if (live !== undefined) {
89
+ return live;
90
+ }
91
+ }
92
+
93
+ const module = this.#compile(descriptor);
94
+
95
+ // an equal descriptor that is already a key keeps its entry, and the dead reference is replaced
96
+ cache.set(descriptor, new WeakRef(module));
97
+
98
+ return module;
76
99
  }
77
100
 
78
101
  }
@@ -0,0 +1,75 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Grass surfaces</title>
7
+ <style>
8
+ :root {
9
+ color-scheme: dark;
10
+ }
11
+
12
+ html, body {
13
+ margin: 0;
14
+ height: 100%;
15
+ overflow: hidden;
16
+ background: #101215;
17
+ color: #e3e5e8;
18
+ font: 13px/1.4 'Segoe UI', system-ui, sans-serif;
19
+ }
20
+
21
+ #viewport {
22
+ position: absolute;
23
+ inset: 0;
24
+ }
25
+
26
+ #legend {
27
+ position: absolute;
28
+ left: 12px;
29
+ top: 12px;
30
+ padding: 10px 12px;
31
+ background: rgba(14, 15, 20, 0.78);
32
+ border: 1px solid rgba(255, 255, 255, 0.1);
33
+ border-radius: 4px;
34
+ max-width: 360px;
35
+ }
36
+
37
+ #legend h1 {
38
+ font-size: 14px;
39
+ margin: 0 0 6px;
40
+ }
41
+
42
+ #legend p {
43
+ margin: 4px 0;
44
+ color: #a8adb5;
45
+ }
46
+
47
+ #status {
48
+ font-variant-numeric: tabular-nums;
49
+ color: #e3e5e8;
50
+ white-space: pre;
51
+ }
52
+
53
+ #message {
54
+ position: absolute;
55
+ inset: 0;
56
+ display: none;
57
+ place-items: center;
58
+ white-space: pre-wrap;
59
+ padding: 24px;
60
+ }
61
+ </style>
62
+ </head>
63
+ <body tabindex="0">
64
+ <div id="viewport"></div>
65
+ <div id="legend">
66
+ <h1>Grass surfaces</h1>
67
+ <p>A field of two sheets, a boulder sunk into one and a hill over a cave on the other, sampled as one
68
+ surface; and a platform of two sheets and a crate that moves as another.</p>
69
+ <p>A grey slab hangs over the field and is no member of it.</p>
70
+ <p id="status"></p>
71
+ </div>
72
+ <div id="message"></div>
73
+ <script type="module" src="./main.js"></script>
74
+ </body>
75
+ </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/grass_surfaces/main.js"],"names":[],"mappings":""}