@woosh/meep-engine 3.11.1 → 3.11.3

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 (225) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/package.json +1 -1
  3. package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
  4. package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +294 -290
  5. package/src/engine/graphics3/ParticipatingMedia.d.ts +111 -0
  6. package/src/engine/graphics3/ParticipatingMedia.d.ts.map +1 -0
  7. package/src/engine/graphics3/ParticipatingMedia.js +203 -0
  8. package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.d.ts +34 -0
  9. package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.d.ts.map +1 -0
  10. package/src/engine/graphics3/ParticipatingMediaSerializationAdapter.js +73 -0
  11. package/src/engine/graphics3/ParticipatingMediaSystem3.d.ts +87 -0
  12. package/src/engine/graphics3/ParticipatingMediaSystem3.d.ts.map +1 -0
  13. package/src/engine/graphics3/ParticipatingMediaSystem3.js +184 -0
  14. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  15. package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.d.ts +16 -2
  16. package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.d.ts.map +1 -1
  17. package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.js +28 -4
  18. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts +1 -1
  19. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts.map +1 -1
  20. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.js +5 -2
  21. package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +564 -451
  22. package/src/shade/device/ShadeGPUCommandContext.d.ts +18 -2
  23. package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
  24. package/src/shade/device/ShadeGPUCommandContext.js +994 -940
  25. package/src/shade/device/immediate_data_supported.d.ts +33 -0
  26. package/src/shade/device/immediate_data_supported.d.ts.map +1 -0
  27. package/src/shade/device/immediate_data_supported.js +53 -0
  28. package/src/shade/device/mock/SoftwareGPUCommandEncoder.d.ts +18 -0
  29. package/src/shade/device/mock/SoftwareGPUCommandEncoder.d.ts.map +1 -1
  30. package/src/shade/device/mock/SoftwareGPUCommandEncoder.js +24 -0
  31. package/src/shade/device/mock/SoftwareGPUComputePassEncoder.d.ts +7 -0
  32. package/src/shade/device/mock/SoftwareGPUComputePassEncoder.d.ts.map +1 -1
  33. package/src/shade/device/mock/SoftwareGPUComputePassEncoder.js +49 -1
  34. package/src/shade/device/mock/SoftwareGPUDevice.d.ts.map +1 -1
  35. package/src/shade/device/mock/SoftwareGPUDevice.js +20 -2
  36. package/src/shade/device/mock/SoftwareGPUImmediateData.d.ts +65 -0
  37. package/src/shade/device/mock/SoftwareGPUImmediateData.d.ts.map +1 -0
  38. package/src/shade/device/mock/SoftwareGPUImmediateData.js +160 -0
  39. package/src/shade/device/mock/SoftwareGPURenderPassEncoder.d.ts +7 -0
  40. package/src/shade/device/mock/SoftwareGPURenderPassEncoder.d.ts.map +1 -1
  41. package/src/shade/device/mock/SoftwareGPURenderPassEncoder.js +50 -0
  42. package/src/shade/device/mock/pipeline_immediate_size.d.ts +11 -0
  43. package/src/shade/device/mock/pipeline_immediate_size.d.ts.map +1 -0
  44. package/src/shade/device/mock/pipeline_immediate_size.js +18 -0
  45. package/src/shade/device/pipeline/PipelineLayoutManager.d.ts.map +1 -1
  46. package/src/shade/device/pipeline/PipelineLayoutManager.js +1 -0
  47. package/src/shade/playground/volumetrics_froxel/README.md +104 -1
  48. package/src/shade/playground/volumetrics_froxel/index.html +20 -1
  49. package/src/shade/playground/volumetrics_froxel/main.d.ts.map +1 -1
  50. package/src/shade/playground/volumetrics_froxel/main.js +298 -0
  51. package/src/shade/playground/volumetrics_froxel/measure.d.ts +119 -0
  52. package/src/shade/playground/volumetrics_froxel/measure.d.ts.map +1 -0
  53. package/src/shade/playground/volumetrics_froxel/measure.js +559 -0
  54. package/src/shade/renderer/GraphicsContext.d.ts +9 -2
  55. package/src/shade/renderer/GraphicsContext.d.ts.map +1 -1
  56. package/src/shade/renderer/GraphicsContext.js +13 -1
  57. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  58. package/src/shade/renderer/Renderer.js +22 -18
  59. package/src/shade/renderer/atmosphere/GPUSky.d.ts.map +1 -1
  60. package/src/shade/renderer/atmosphere/GPUSky.js +145 -142
  61. package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.d.ts +34 -0
  62. package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.d.ts.map +1 -0
  63. package/src/shade/renderer/atmosphere/MULTISCATTER_LUT_CONFIG.js +36 -0
  64. package/src/shade/renderer/atmosphere/SAMPLER_SKY_LUT.d.ts +20 -0
  65. package/src/shade/renderer/atmosphere/SAMPLER_SKY_LUT.d.ts.map +1 -0
  66. package/src/shade/renderer/atmosphere/SAMPLER_SKY_LUT.js +25 -0
  67. package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.d.ts +14 -1
  68. package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.d.ts.map +1 -1
  69. package/src/shade/renderer/atmosphere/chunk_get_multiscatter_values.js +163 -177
  70. package/src/shade/renderer/atmosphere/chunk_multiscatter_sample_direction.d.ts +20 -0
  71. package/src/shade/renderer/atmosphere/chunk_multiscatter_sample_direction.d.ts.map +1 -0
  72. package/src/shade/renderer/atmosphere/chunk_multiscatter_sample_direction.js +46 -0
  73. package/src/shade/renderer/atmosphere/chunk_sample_multiscatter_lut.d.ts +11 -1
  74. package/src/shade/renderer/atmosphere/chunk_sample_multiscatter_lut.d.ts.map +1 -1
  75. package/src/shade/renderer/atmosphere/chunk_sample_multiscatter_lut.js +57 -27
  76. package/src/shade/renderer/atmosphere/chunk_sample_transmittance_lut.d.ts +19 -1
  77. package/src/shade/renderer/atmosphere/chunk_sample_transmittance_lut.d.ts.map +1 -1
  78. package/src/shade/renderer/atmosphere/chunk_sample_transmittance_lut.js +69 -33
  79. package/src/shade/renderer/atmosphere/chunk_sky_lut_compute_uv.d.ts +13 -0
  80. package/src/shade/renderer/atmosphere/chunk_sky_lut_compute_uv.d.ts.map +1 -1
  81. package/src/shade/renderer/atmosphere/chunk_sky_lut_compute_uv.js +35 -35
  82. package/src/shade/renderer/atmosphere/chunk_sky_lut_params.d.ts +13 -0
  83. package/src/shade/renderer/atmosphere/chunk_sky_lut_params.d.ts.map +1 -0
  84. package/src/shade/renderer/atmosphere/chunk_sky_lut_params.js +38 -0
  85. package/src/shade/renderer/atmosphere/chunk_sky_lut_texel_to_unit.d.ts +17 -0
  86. package/src/shade/renderer/atmosphere/chunk_sky_lut_texel_to_unit.d.ts.map +1 -0
  87. package/src/shade/renderer/atmosphere/chunk_sky_lut_texel_to_unit.js +29 -0
  88. package/src/shade/renderer/atmosphere/chunk_sky_lut_uv.d.ts +21 -0
  89. package/src/shade/renderer/atmosphere/chunk_sky_lut_uv.d.ts.map +1 -0
  90. package/src/shade/renderer/atmosphere/chunk_sky_lut_uv.js +42 -0
  91. package/src/shade/renderer/atmosphere/shader_multiscatter_lut.d.ts +2 -2
  92. package/src/shade/renderer/atmosphere/shader_multiscatter_lut.d.ts.map +1 -1
  93. package/src/shade/renderer/atmosphere/shader_multiscatter_lut.js +165 -84
  94. package/src/shade/renderer/atmosphere/shader_sky_irradiance_lut.d.ts.map +1 -1
  95. package/src/shade/renderer/atmosphere/shader_sky_irradiance_lut.js +215 -204
  96. package/src/shade/renderer/atmosphere/shader_transmittance_lut.d.ts.map +1 -1
  97. package/src/shade/renderer/atmosphere/shader_transmittance_lut.js +79 -67
  98. package/src/shade/renderer/light/cluster/graph_assign_clsuters.d.ts.map +1 -1
  99. package/src/shade/renderer/light/cluster/graph_assign_clsuters.js +6 -2
  100. package/src/shade/renderer/postprocess/gtao/GTAO.d.ts.map +1 -1
  101. package/src/shade/renderer/postprocess/gtao/GTAO.js +4 -0
  102. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  103. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  104. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +341 -345
  105. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts +0 -2
  106. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.d.ts.map +1 -1
  107. package/src/shade/renderer/rasterize/bucket/shader_read_out_bucket.js +58 -57
  108. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
  109. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +7 -3
  110. package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.d.ts.map +1 -1
  111. package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.js +77 -81
  112. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts.map +1 -1
  113. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +5 -1
  114. package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
  115. package/src/shade/renderer/shader/ComputeShader.js +6 -2
  116. package/src/shade/renderer/shader/ImageShader.d.ts.map +1 -1
  117. package/src/shade/renderer/shader/ImageShader.js +4 -1
  118. package/src/shade/renderer/shader/ShaderDescriptor.d.ts.map +1 -1
  119. package/src/shade/renderer/shader/ShaderDescriptor.js +26 -0
  120. package/src/shade/renderer/shader/chunk/atmosphere/ATMOSPHERE_RADII_DECLARATION.d.ts +18 -0
  121. package/src/shade/renderer/shader/chunk/atmosphere/ATMOSPHERE_RADII_DECLARATION.d.ts.map +1 -0
  122. package/src/shade/renderer/shader/chunk/atmosphere/ATMOSPHERE_RADII_DECLARATION.js +32 -0
  123. package/src/shade/renderer/shader/chunk/atmosphere/PLANET_CENTER_DECLARATION.d.ts +7 -0
  124. package/src/shade/renderer/shader/chunk/atmosphere/PLANET_CENTER_DECLARATION.d.ts.map +1 -1
  125. package/src/shade/renderer/shader/chunk/atmosphere/PLANET_CENTER_DECLARATION.js +17 -6
  126. package/src/shade/renderer/shader/chunk/atmosphere/chunk_atmosphere_ray_bounds.d.ts +21 -0
  127. package/src/shade/renderer/shader/chunk/atmosphere/chunk_atmosphere_ray_bounds.d.ts.map +1 -0
  128. package/src/shade/renderer/shader/chunk/atmosphere/chunk_atmosphere_ray_bounds.js +69 -0
  129. package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_contains_aabb3.d.ts +9 -0
  130. package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_contains_aabb3.d.ts.map +1 -0
  131. package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_contains_aabb3.js +22 -0
  132. package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_from_transformed_corners.d.ts +16 -0
  133. package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_from_transformed_corners.d.ts.map +1 -0
  134. package/src/shade/renderer/shader/chunk/geometry/aabb3/chunk_aabb3_from_transformed_corners.js +41 -0
  135. package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_m4.d.ts +11 -0
  136. package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_m4.d.ts.map +1 -1
  137. package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_m4.js +15 -19
  138. package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_plane_matrix.d.ts +23 -0
  139. package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_plane_matrix.d.ts.map +1 -0
  140. package/src/shade/renderer/shader/chunk/geometry/frustum/chunk_frustum_transform_plane_matrix.js +44 -0
  141. package/src/shade/renderer/shader/chunk/geometry/octahedron/chunk_uv_octahedral_unit_decode.d.ts.map +1 -1
  142. package/src/shade/renderer/shader/chunk/geometry/octahedron/chunk_uv_octahedral_unit_decode.js +1 -4
  143. package/src/shade/renderer/shader/compiler/CodeChunk.d.ts +7 -1
  144. package/src/shade/renderer/shader/compiler/CodeChunk.d.ts.map +1 -1
  145. package/src/shade/renderer/shader/compiler/CodeChunk.js +37 -2
  146. package/src/shade/renderer/shader/graph/compute/compute_binding_read_names.d.ts.map +1 -1
  147. package/src/shade/renderer/shader/graph/compute/compute_binding_read_names.js +6 -0
  148. package/src/shade/renderer/shader/graph/compute/graph_compute_indirect_pass.js +1 -1
  149. package/src/shade/renderer/shader/graph/compute/graph_compute_pass.js +1 -1
  150. package/src/shade/renderer/shader/graph/graph_image_pass.js +1 -1
  151. package/src/shade/renderer/shader/graph/graph_prepare_bindings.d.ts.map +1 -1
  152. package/src/shade/renderer/shader/graph/graph_prepare_bindings.js +7 -0
  153. package/src/shade/renderer/shader/graph/graph_prepare_pass_input_data.d.ts +3 -1
  154. package/src/shade/renderer/shader/graph/graph_prepare_pass_input_data.d.ts.map +1 -1
  155. package/src/shade/renderer/shader/graph/graph_prepare_pass_input_data.js +12 -1
  156. package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts.map +1 -1
  157. package/src/shade/renderer/shader/pass/RenderPassDescriptor.js +1 -0
  158. package/src/shade/renderer/shader/resource/IMMEDIATE_DATA.d.ts +21 -0
  159. package/src/shade/renderer/shader/resource/IMMEDIATE_DATA.d.ts.map +1 -0
  160. package/src/shade/renderer/shader/resource/IMMEDIATE_DATA.js +21 -0
  161. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts +59 -1
  162. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
  163. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +195 -2
  164. package/src/shade/renderer/shader/type/type_has_arrays.d.ts +14 -0
  165. package/src/shade/renderer/shader/type/type_has_arrays.d.ts.map +1 -0
  166. package/src/shade/renderer/shader/type/type_has_arrays.js +33 -0
  167. package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.d.ts +14 -13
  168. package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.d.ts.map +1 -1
  169. package/src/shade/renderer/shadow/map/shader/chunk_shadowmap_sample_point2.js +133 -129
  170. package/src/shade/renderer/view/GPUViewSkyContext.d.ts.map +1 -1
  171. package/src/shade/renderer/view/GPUViewSkyContext.js +169 -173
  172. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
  173. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +480 -315
  174. package/src/shade/renderer/volumetrics/NOTES.md +887 -8
  175. package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts +5 -0
  176. package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts.map +1 -1
  177. package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.js +21 -2
  178. package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts +26 -0
  179. package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts.map +1 -1
  180. package/src/shade/renderer/volumetrics/SceneVolumetrics.js +64 -21
  181. package/src/shade/renderer/volumetrics/VOLUMETRICS_METADATA_STRUCT.d.ts.map +1 -1
  182. package/src/shade/renderer/volumetrics/VOLUMETRICS_METADATA_STRUCT.js +84 -28
  183. package/src/shade/renderer/volumetrics/VOLUMETRICS_SUN_SHADOW_RESOLUTION.d.ts +98 -0
  184. package/src/shade/renderer/volumetrics/VOLUMETRICS_SUN_SHADOW_RESOLUTION.d.ts.map +1 -0
  185. package/src/shade/renderer/volumetrics/VOLUMETRICS_SUN_SHADOW_RESOLUTION.js +111 -0
  186. package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.d.ts +84 -0
  187. package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.d.ts.map +1 -0
  188. package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.js +252 -0
  189. package/src/shade/renderer/volumetrics/chunk_integrate_optical_depth.js +75 -75
  190. package/src/shade/renderer/volumetrics/chunk_volumetrics_local_light_shadow.d.ts +43 -0
  191. package/src/shade/renderer/volumetrics/chunk_volumetrics_local_light_shadow.d.ts.map +1 -0
  192. package/src/shade/renderer/volumetrics/chunk_volumetrics_local_light_shadow.js +145 -0
  193. package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.d.ts +20 -0
  194. package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.d.ts.map +1 -0
  195. package/src/shade/renderer/volumetrics/chunk_volumetrics_sample_froxel_extinction.js +48 -0
  196. package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_optical_depth.d.ts +38 -0
  197. package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_optical_depth.d.ts.map +1 -0
  198. package/src/shade/renderer/volumetrics/chunk_volumetrics_sun_optical_depth.js +130 -0
  199. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +18 -3
  200. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
  201. package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +193 -70
  202. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts +16 -0
  203. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts.map +1 -1
  204. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.js +83 -15
  205. package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.d.ts.map +1 -1
  206. package/src/shade/renderer/volumetrics/shader_volumetrics_build_participating_media.js +29 -18
  207. package/src/shade/renderer/volumetrics/shader_volumetrics_build_scattering_lut.js +260 -260
  208. package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.d.ts +58 -0
  209. package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.d.ts.map +1 -0
  210. package/src/shade/renderer/volumetrics/shader_volumetrics_build_sun_shadow_volume.js +290 -0
  211. package/src/shade/wgsl/emulator/CPUBitmapData.d.ts +25 -0
  212. package/src/shade/wgsl/emulator/CPUBitmapData.d.ts.map +1 -1
  213. package/src/shade/wgsl/emulator/CPUBitmapData.js +33 -0
  214. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +2228 -2215
  215. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  216. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +210 -2
  217. package/src/shade/wgsl/emulator/cpu_texture_gather.d.ts +69 -0
  218. package/src/shade/wgsl/emulator/cpu_texture_gather.d.ts.map +1 -0
  219. package/src/shade/wgsl/emulator/cpu_texture_gather.js +148 -0
  220. package/src/shade/wgsl/emulator/cpu_texture_sample.d.ts +16 -0
  221. package/src/shade/wgsl/emulator/cpu_texture_sample.d.ts.map +1 -1
  222. package/src/shade/wgsl/emulator/cpu_texture_sample.js +176 -172
  223. package/src/shade/renderer/volumetrics/VOLUMETRICS_WORKGROUP_RESOLUTION.d.ts +0 -2
  224. package/src/shade/renderer/volumetrics/VOLUMETRICS_WORKGROUP_RESOLUTION.d.ts.map +0 -1
  225. package/src/shade/renderer/volumetrics/VOLUMETRICS_WORKGROUP_RESOLUTION.js +0 -1
@@ -0,0 +1,184 @@
1
+ import { assert } from "../../core/assert.js";
2
+ import { isArrayEqualStrict } from "../../core/collection/array/isArrayEqualStrict.js";
3
+ import { ParticipatingMediaVolume } from "../../shade/renderer/volumetrics/ParticipatingMediaVolume.js";
4
+ import { System } from "../ecs/System.js";
5
+ import { Transform } from "../ecs/transform/Transform.js";
6
+ import { ParticipatingMedia } from "./ParticipatingMedia.js";
7
+
8
+ /**
9
+ * Mirrors fog, smoke and cloud entities into Shade's volumetrics.
10
+ *
11
+ * The same shape as {@link LightSystem3}: the ECS says what exists and where, and this keeps the
12
+ * renderer's own objects in step. A {@link ParticipatingMediaVolume} is a unit cube posed by a
13
+ * transform, so an entity's `Transform` is the volume — position, size and orientation with no
14
+ * translation step in between.
15
+ *
16
+ * **The transform is taken as world-space, with no hierarchy applied**, which is what the volume
17
+ * model can express: a volume is an oriented box in the scene and Shade has no parent chain to walk
18
+ * for it. Parenting a fog volume to a moving entity therefore leaves the fog where the child's own
19
+ * transform puts it. The lights are placed the same way, for the same reason.
20
+ *
21
+ * **Changes are polled once a frame rather than subscribed to.** A `Transform` announces itself and
22
+ * nothing else here does — a density tuned by an editor slider, a particle spec swapped wholesale
23
+ * for a different Mie solution — so subscribing would cover one field in three and the other two
24
+ * would still have to be polled. Two paths that have to agree, where one does the whole job. It
25
+ * costs about two dozen float comparisons per volume per frame and a scene holds volumes in the
26
+ * tens, so the comparison is cheaper than the signal plumbing it replaces. The price is latency: a
27
+ * change is visible within a frame rather than instantly.
28
+ *
29
+ * **Nothing is uploaded unless something actually changed.** The GPU table is repacked whole
30
+ * whenever {@link SceneVolumetrics.version} moves, so an unconditional copy every frame would
31
+ * re-upload every volume in the scene forever. The comparison is what decides, and on almost every
32
+ * frame it decides nothing has to happen.
33
+ *
34
+ * @see ParticipatingMedia the component
35
+ * @see SceneVolumetrics what the volumes are handed to
36
+ */
37
+ export class ParticipatingMediaSystem3 extends System {
38
+
39
+ dependencies = [ParticipatingMedia, Transform];
40
+
41
+ /**
42
+ * @type {GraphicsEngine3}
43
+ */
44
+ #graphics;
45
+
46
+ /**
47
+ * @type {Scene}
48
+ */
49
+ #scene;
50
+
51
+ /**
52
+ * @type {Map<number, {component: ParticipatingMedia, transform: Transform, volume: ParticipatingMediaVolume}>}
53
+ */
54
+ #entries = new Map();
55
+
56
+ /**
57
+ * @param {GraphicsEngine3} graphics
58
+ * @param {Scene} scene
59
+ */
60
+ constructor(graphics, scene) {
61
+ super();
62
+
63
+ assert.defined(graphics, 'graphics');
64
+ assert.defined(scene, 'scene');
65
+ assert.equal(scene.isScene, true, 'scene.isScene !== true');
66
+
67
+ this.#graphics = graphics;
68
+ this.#scene = scene;
69
+ }
70
+
71
+ async startup(entityManager) {
72
+ this.entityManager = entityManager;
73
+
74
+ this.#graphics.set_scene(this.#scene);
75
+ }
76
+
77
+ async shutdown(entityManager) {
78
+ for (const entity of Array.from(this.#entries.keys())) {
79
+ this.#drop(entity);
80
+ }
81
+ }
82
+
83
+ /**
84
+ * @param {ParticipatingMedia} component
85
+ * @param {Transform} transform
86
+ * @param {number} entity
87
+ */
88
+ link(component, transform, entity) {
89
+ const volume = new ParticipatingMediaVolume();
90
+
91
+ participating_media_volume_write(volume, component, transform);
92
+
93
+ this.#scene.volumetrics.add(volume);
94
+
95
+ this.#entries.set(entity, { component, transform, volume });
96
+ }
97
+
98
+ /**
99
+ * @param {ParticipatingMedia} component
100
+ * @param {Transform} transform
101
+ * @param {number} entity
102
+ */
103
+ unlink(component, transform, entity) {
104
+ this.#drop(entity);
105
+ }
106
+
107
+ /**
108
+ * @param {number} time_delta_seconds
109
+ */
110
+ update(time_delta_seconds) {
111
+ const volumetrics = this.#scene.volumetrics;
112
+
113
+ for (const entry of this.#entries.values()) {
114
+ const volume = entry.volume;
115
+
116
+ if (participating_media_volume_is_current(volume, entry.component, entry.transform)) {
117
+ continue;
118
+ }
119
+
120
+ participating_media_volume_write(volume, entry.component, entry.transform);
121
+
122
+ volumetrics.invalidate();
123
+ }
124
+ }
125
+
126
+ /**
127
+ * @param {number} entity
128
+ */
129
+ #drop(entity) {
130
+ const entry = this.#entries.get(entity);
131
+
132
+ if (entry === undefined) {
133
+ return;
134
+ }
135
+
136
+ this.#scene.volumetrics.remove(entry.volume);
137
+
138
+ this.#entries.delete(entity);
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Copy what the component and its transform say onto the volume Shade will render.
144
+ *
145
+ * The particle spec is **copied, not referenced**: two entities are routinely built from the same
146
+ * blueprint and would otherwise share one spec, so tuning one volume's particle would silently
147
+ * retune the other's.
148
+ *
149
+ * @param {ParticipatingMediaVolume} volume Shade's
150
+ * @param {ParticipatingMedia} component meep's
151
+ * @param {Transform} transform where the box is
152
+ */
153
+ export function participating_media_volume_write(volume, component, transform) {
154
+ volume.density = component.density;
155
+ volume.fade_distance = component.fade_distance;
156
+
157
+ volume.particle_spec.copy(component.particle_spec);
158
+
159
+ volume.transform.copy(transform);
160
+ }
161
+
162
+ /**
163
+ * Whether the volume already says what the component and transform say.
164
+ *
165
+ * True on all but a handful of frames, which is the point of asking: a `false` here costs the whole
166
+ * scene's volumetrics table a trip to the GPU.
167
+ *
168
+ * **The transform is compared by its matrix rather than by `Transform.equals`**, because the matrix
169
+ * is the entire transform the GPU is given — the volume's position, rotation and scale are never
170
+ * read on their own. That makes this exactly the question worth asking, "would the upload differ",
171
+ * and it catches a transform posed by writing its matrix, which comparing position, rotation and
172
+ * scale would not.
173
+ *
174
+ * @param {ParticipatingMediaVolume} volume
175
+ * @param {ParticipatingMedia} component
176
+ * @param {Transform} transform
177
+ * @returns {boolean}
178
+ */
179
+ export function participating_media_volume_is_current(volume, component, transform) {
180
+ return volume.density === component.density
181
+ && volume.fade_distance === component.fade_distance
182
+ && isArrayEqualStrict(volume.transform.matrix, transform.matrix)
183
+ && volume.particle_spec.equals(component.particle_spec);
184
+ }
@@ -64,11 +64,11 @@ export class FluidObstacleSystem extends System<any> {
64
64
  /**
65
65
  * @param {FluidComponent} fluid
66
66
  */
67
- static "__#354@#refresh_masks"(fluid: FluidComponent): void;
67
+ static "__#356@#refresh_masks"(fluid: FluidComponent): void;
68
68
  /**
69
69
  * @param {FluidComponent} fluid
70
70
  */
71
- static "__#354@#clear_field"(fluid: FluidComponent): void;
71
+ static "__#356@#clear_field"(fluid: FluidComponent): void;
72
72
  /**
73
73
  * Mark every cell of `fluid` whose centre lies within `inflation` of the
74
74
  * posed shape as solid. Iteration is clipped to the shape's world AABB
@@ -80,7 +80,7 @@ export class FluidObstacleSystem extends System<any> {
80
80
  * @param {number} inflation world-units SDF threshold
81
81
  * @param {Float64Array} point length-3 scratch
82
82
  */
83
- static "__#354@#voxelize"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array): void;
83
+ static "__#356@#voxelize"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array): void;
84
84
  /**
85
85
  * Write the obstacle's translation velocity onto every face of every cell
86
86
  * it voxelized — the moving-wall boundary condition. Runs AFTER the mask
@@ -100,7 +100,7 @@ export class FluidObstacleSystem extends System<any> {
100
100
  * @param {number} wvy
101
101
  * @param {number} wvz
102
102
  */
103
- static "__#354@#stamp_wall_velocity"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array, wvx: number, wvy: number, wvz: number): void;
103
+ static "__#356@#stamp_wall_velocity"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array, wvx: number, wvy: number, wvz: number): void;
104
104
  constructor();
105
105
  dependencies: (typeof FluidObstacle)[];
106
106
  components_used: (ResourceAccessSpecification<typeof Transform> | ResourceAccessSpecification<typeof RigidBody> | ResourceAccessSpecification<typeof Collider> | ResourceAccessSpecification<typeof FluidComponent> | ResourceAccessSpecification<typeof FluidObstacle>)[];
@@ -12,12 +12,13 @@ export class PipelineLayoutDescriptor extends ObjectDescriptorBase {
12
12
  * @param {GPUShaderStage|number} stage
13
13
  * @param {(BufferBindingLayout|SamplerBindingLayout|TextureBindingLayout|StorageTextureBindingLayout|ExternalTextureBindingLayout)[][]} bindings
14
14
  */
15
- static forStage(stage: GPUShaderStage | number, bindings: (BufferBindingLayout | SamplerBindingLayout | TextureBindingLayout | StorageTextureBindingLayout | ExternalTextureBindingLayout)[][]): PipelineLayoutDescriptor;
15
+ static forStage(stage: GPUShaderStage | number, bindings: (BufferBindingLayout | SamplerBindingLayout | TextureBindingLayout | StorageTextureBindingLayout | ExternalTextureBindingLayout)[][], immediate_size?: number): PipelineLayoutDescriptor;
16
16
  /**
17
17
  *
18
18
  * @param {BindGroupLayoutDescriptor[]} bind_groups
19
+ * @param {number} [immediate_size] bytes of immediate data, 0 when the shader declares none
19
20
  */
20
- static from(bind_groups: BindGroupLayoutDescriptor[]): PipelineLayoutDescriptor;
21
+ static from(bind_groups: BindGroupLayoutDescriptor[], immediate_size?: number): PipelineLayoutDescriptor;
21
22
  /**
22
23
  *
23
24
  * @param {JSONPipelineLayoutDescriptor} json
@@ -29,6 +30,19 @@ export class PipelineLayoutDescriptor extends ObjectDescriptorBase {
29
30
  * @type {BindGroupLayoutDescriptor[]}
30
31
  */
31
32
  bindGroupLayouts: BindGroupLayoutDescriptor[];
33
+ /**
34
+ * Bytes of immediate data the pipelines using this layout read, 0 when they read none.
35
+ *
36
+ * Not a bind group and not a binding — immediate data is part of the shader interface without
37
+ * being part of its resource interface, so it hangs off the layout itself.
38
+ *
39
+ * Must be a multiple of 4 and no larger than the device's `maxImmediateSize`; both are
40
+ * validated where the layout is created, not here, because this descriptor never sees a device.
41
+ *
42
+ * @see https://www.w3.org/TR/webgpu/#dom-gpupipelinelayoutdescriptor-immediatesize
43
+ * @type {number}
44
+ */
45
+ immediateSize: number;
32
46
  /**
33
47
  *
34
48
  * @param {JSONPipelineLayoutDescriptor} json
@@ -1 +1 @@
1
- {"version":3,"file":"PipelineLayoutDescriptor.d.ts","sourceRoot":"","sources":["../../../../../src/shade/descriptor/pipeline/PipelineLayoutDescriptor.js"],"names":[],"mappings":"AASA;;;;GAIG;AAEH;;GAEG;AACH;IAQI;;;;OAIG;IACH,uBAHW,iBAAe,MAAM,YACrB,CAAC,8HAAsH,CAAC,EAAE,EAAE,4BAgBtI;IAGD;;;OAGG;IACH,yBAFW,yBAAyB,EAAE,4BAsBrC;IAED;;;;OAIG;IACH,gDAFY,wBAAwB,CAQnC;IAjED;;;OAGG;IACH,kBAFU,yBAAyB,EAAE,CAEhB;IAgErB;;;OAGG;IACH,8CAQC;IASD,4BAOC;IAED;;;OAGG;IACH,YAFW,wBAAwB,QAKlC;IAED;;;OAGG;IACH,SAFY,wBAAwB,CAQnC;IAGL;;;OAGG;IACH,qCAFU,OAAO,CAE4C;CAN5D;;qCAnIoC,4BAA4B;0CADvB,yCAAyC"}
1
+ {"version":3,"file":"PipelineLayoutDescriptor.d.ts","sourceRoot":"","sources":["../../../../../src/shade/descriptor/pipeline/PipelineLayoutDescriptor.js"],"names":[],"mappings":"AASA;;;;GAIG;AAEH;;GAEG;AACH;IAsBI;;;;OAIG;IACH,uBAHW,iBAAe,MAAM,YACrB,CAAC,8HAAsH,CAAC,EAAE,EAAE,qDAgBtI;IAGD;;;;OAIG;IACH,yBAHW,yBAAyB,EAAE,mBAC3B,MAAM,4BAyBhB;IAED;;;;OAIG;IACH,gDAFY,wBAAwB,CAQnC;IAnFD;;;OAGG;IACH,kBAFU,yBAAyB,EAAE,CAEhB;IAErB;;;;;;;;;;;OAWG;IACH,eAFU,MAAM,CAEC;IAoEjB;;;OAGG;IACH,8CASC;IAYD,4BAQC;IAED;;;OAGG;IACH,YAFW,wBAAwB,QAMlC;IAED;;;OAGG;IACH,SAFY,wBAAwB,CAQnC;IAGL;;;OAGG;IACH,qCAFU,OAAO,CAE4C;CAN5D;;qCA3JoC,4BAA4B;0CADvB,yCAAyC"}
@@ -24,12 +24,26 @@ export class PipelineLayoutDescriptor extends ObjectDescriptorBase {
24
24
  */
25
25
  bindGroupLayouts = []
26
26
 
27
+ /**
28
+ * Bytes of immediate data the pipelines using this layout read, 0 when they read none.
29
+ *
30
+ * Not a bind group and not a binding — immediate data is part of the shader interface without
31
+ * being part of its resource interface, so it hangs off the layout itself.
32
+ *
33
+ * Must be a multiple of 4 and no larger than the device's `maxImmediateSize`; both are
34
+ * validated where the layout is created, not here, because this descriptor never sees a device.
35
+ *
36
+ * @see https://www.w3.org/TR/webgpu/#dom-gpupipelinelayoutdescriptor-immediatesize
37
+ * @type {number}
38
+ */
39
+ immediateSize = 0
40
+
27
41
  /**
28
42
  *
29
43
  * @param {GPUShaderStage|number} stage
30
44
  * @param {(BufferBindingLayout|SamplerBindingLayout|TextureBindingLayout|StorageTextureBindingLayout|ExternalTextureBindingLayout)[][]} bindings
31
45
  */
32
- static forStage(stage, bindings) {
46
+ static forStage(stage, bindings, immediate_size = 0) {
33
47
  assert.isArray(bindings, 'bindings');
34
48
 
35
49
  const bind_group_count = bindings.length;
@@ -42,20 +56,24 @@ export class PipelineLayoutDescriptor extends ObjectDescriptorBase {
42
56
  bind_groups[i] = BindGroupLayoutDescriptor.forStage(stage, "", binding_set);
43
57
  }
44
58
 
45
- return PipelineLayoutDescriptor.from(bind_groups);
59
+ return PipelineLayoutDescriptor.from(bind_groups, immediate_size);
46
60
  }
47
61
 
48
62
 
49
63
  /**
50
64
  *
51
65
  * @param {BindGroupLayoutDescriptor[]} bind_groups
66
+ * @param {number} [immediate_size] bytes of immediate data, 0 when the shader declares none
52
67
  */
53
- static from(bind_groups) {
68
+ static from(bind_groups, immediate_size = 0) {
54
69
 
55
70
  assert.isArray(bind_groups, 'bind_groups');
71
+ assert.isNonNegativeInteger(immediate_size, 'immediate_size');
56
72
 
57
73
  const r = new PipelineLayoutDescriptor();
58
74
 
75
+ r.immediateSize = immediate_size;
76
+
59
77
  const count = bind_groups.length;
60
78
 
61
79
  for (let i = 0; i < count; i++) {
@@ -98,12 +116,16 @@ export class PipelineLayoutDescriptor extends ObjectDescriptorBase {
98
116
  const bindGroupLayouts = json.bindGroupLayouts ?? [];
99
117
 
100
118
  this.bindGroupLayouts = bindGroupLayouts.map(BindGroupLayoutDescriptor.fromJSON);
119
+ this.immediateSize = json.immediateSize ?? 0;
101
120
  }
102
121
 
103
122
  hash() {
104
123
  return combine_hash(
105
124
  super.hash(),
106
- computeHashArray(this.bindGroupLayouts, invokeObjectHash)
125
+ computeHashArray(this.bindGroupLayouts, invokeObjectHash),
126
+ // two layouts that differ only in immediate size are different layouts; leaving this out
127
+ // would alias them in the manager's cache and hand a pipeline someone else's budget
128
+ this.immediateSize
107
129
  );
108
130
  }
109
131
 
@@ -113,6 +135,7 @@ export class PipelineLayoutDescriptor extends ObjectDescriptorBase {
113
135
  }
114
136
 
115
137
  return super.equals(other)
138
+ && this.immediateSize === other.immediateSize
116
139
  && isArrayEqual(this.bindGroupLayouts, other.bindGroupLayouts);
117
140
  }
118
141
 
@@ -123,6 +146,7 @@ export class PipelineLayoutDescriptor extends ObjectDescriptorBase {
123
146
  copy(other) {
124
147
  super.copy(other);
125
148
  this.bindGroupLayouts = other.bindGroupLayouts.map(optional_clone);
149
+ this.immediateSize = other.immediateSize;
126
150
  }
127
151
 
128
152
  /**
@@ -12,7 +12,7 @@ export class ComputePipelineDescriptor extends PipelineDescriptorBase {
12
12
  * @param {(BufferBindingLayout|SamplerBindingLayout|TextureBindingLayout|StorageTextureBindingLayout|ExternalTextureBindingLayout)[][]} bindings
13
13
  * @param {Object<number>} [constants]
14
14
  */
15
- static simplified({ label, code, bindings, constants }: string): ComputePipelineDescriptor;
15
+ static simplified({ label, code, bindings, constants, immediate_size }: string): ComputePipelineDescriptor;
16
16
  /**
17
17
  *
18
18
  * @param {GPUComputePipelineDescriptor} json
@@ -1 +1 @@
1
- {"version":3,"file":"ComputePipelineDescriptor.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.js"],"names":[],"mappings":"AAQA;IAGI;;;;;OAKG;IACH,mBAJW,MAAM,QACN,MAAM,UACN,wBAAwB,6BAalC;IAED;;;;;OAKG;IACH,wDALW,MAAM,6BAsBhB;IAED;;;OAGG;IACH,+EAMC;IAxDD,2BAAkC;IA0DlC;;;OAGG;IACH,mDAMC;IAED;;;;OAIG;IACH,cAHW,yBAAyB,GACxB,OAAO,CAMlB;IAUL;;;OAGG;IACH,sCAFU,OAAO,CAE8C;CAN9D;uCA7FsC,8BAA8B;kCAEnC,yBAAyB;yCADlB,gCAAgC"}
1
+ {"version":3,"file":"ComputePipelineDescriptor.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.js"],"names":[],"mappings":"AAQA;IAGI;;;;;OAKG;IACH,mBAJW,MAAM,QACN,MAAM,UACN,wBAAwB,6BAalC;IAED;;;;;OAKG;IACH,wEALW,MAAM,6BAyBhB;IAED;;;OAGG;IACH,+EAMC;IA3DD,2BAAkC;IA6DlC;;;OAGG;IACH,mDAMC;IAED;;;;OAIG;IACH,cAHW,yBAAyB,GACxB,OAAO,CAMlB;IAUL;;;OAGG;IACH,sCAFU,OAAO,CAE8C;CAN9D;uCAhGsC,8BAA8B;kCAEnC,yBAAyB;yCADlB,gCAAgC"}
@@ -34,7 +34,7 @@ export class ComputePipelineDescriptor extends PipelineDescriptorBase {
34
34
  * @param {(BufferBindingLayout|SamplerBindingLayout|TextureBindingLayout|StorageTextureBindingLayout|ExternalTextureBindingLayout)[][]} bindings
35
35
  * @param {Object<number>} [constants]
36
36
  */
37
- static simplified({ label = "", code, bindings, constants }) {
37
+ static simplified({ label = "", code, bindings, constants, immediate_size = 0 }) {
38
38
  assert.isString(label, 'label');
39
39
 
40
40
  const r = new ComputePipelineDescriptor();
@@ -42,7 +42,10 @@ export class ComputePipelineDescriptor extends PipelineDescriptorBase {
42
42
  r.label = label;
43
43
  r.compute.module = ShaderModuleDescriptor.fromCode(code);
44
44
 
45
- r.layout = PipelineLayoutDescriptor.forStage(GPUShaderStage.COMPUTE, bindings);
45
+ // `immediate_size` must travel with the bindings: a shader that reads immediate data whose
46
+ // layout declares none is a pipeline-creation error on a real device, and the two numbers are
47
+ // derived from the same descriptor
48
+ r.layout = PipelineLayoutDescriptor.forStage(GPUShaderStage.COMPUTE, bindings, immediate_size);
46
49
 
47
50
  if(constants !== undefined){
48
51
  assert.isObject(constants,'constants');