@woosh/meep-engine 3.53.0 → 3.54.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 (194) hide show
  1. package/package.json +1 -1
  2. package/src/core/math/noise/worley_noise_2d.d.ts +14 -0
  3. package/src/core/math/noise/worley_noise_2d.d.ts.map +1 -0
  4. package/src/core/math/noise/worley_noise_2d.js +74 -0
  5. package/src/engine/graphics/texture/atlas/CachingTextureAtlas.d.ts +6 -1
  6. package/src/engine/graphics/texture/atlas/CachingTextureAtlas.d.ts.map +1 -1
  7. package/src/engine/graphics/texture/atlas/CachingTextureAtlas.js +363 -325
  8. package/src/engine/graphics/texture/atlas/ManagedTextureAtlas.d.ts +93 -14
  9. package/src/engine/graphics/texture/atlas/ManagedTextureAtlas.d.ts.map +1 -1
  10. package/src/engine/graphics/texture/atlas/ManagedTextureAtlas.js +322 -183
  11. package/src/engine/graphics/texture/atlas/ReferencedTextureAtlas.d.ts +9 -0
  12. package/src/engine/graphics/texture/atlas/ReferencedTextureAtlas.d.ts.map +1 -1
  13. package/src/engine/graphics/texture/atlas/ReferencedTextureAtlas.js +110 -83
  14. package/src/engine/graphics/texture/atlas/SpriteAtlas.d.ts +42 -0
  15. package/src/engine/graphics/texture/atlas/SpriteAtlas.d.ts.map +1 -0
  16. package/src/engine/{graphics3/decal/DecalAtlas.js → graphics/texture/atlas/SpriteAtlas.js} +202 -194
  17. package/src/engine/graphics/texture/atlas/SpriteAtlasFill.d.ts +12 -0
  18. package/src/engine/graphics/texture/atlas/SpriteAtlasFill.d.ts.map +1 -0
  19. package/src/engine/graphics/texture/atlas/SpriteAtlasFill.js +30 -0
  20. package/src/engine/graphics/texture/atlas/TextureAtlas.d.ts +7 -0
  21. package/src/engine/graphics/texture/atlas/TextureAtlas.d.ts.map +1 -1
  22. package/src/engine/graphics/texture/atlas/TextureAtlas.js +11 -1
  23. package/src/engine/graphics/texture/atlas/sprite_atlas_border.d.ts +52 -0
  24. package/src/engine/graphics/texture/atlas/sprite_atlas_border.d.ts.map +1 -0
  25. package/src/engine/{graphics3/decal/decal_atlas_border.js → graphics/texture/atlas/sprite_atlas_border.js} +69 -69
  26. package/src/engine/graphics3/DecalSystem.d.ts.map +1 -1
  27. package/src/engine/graphics3/DecalSystem.js +447 -450
  28. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +9 -22
  29. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
  30. package/src/engine/graphics3/GPUParticleEmitterSystem.js +892 -951
  31. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  32. package/src/generation/foliage/FOLIAGE_DESIGN.md +2 -1
  33. package/src/generation/foliage/config/BarkMaterialConfig.d.ts +4 -3
  34. package/src/generation/foliage/config/BarkMaterialConfig.d.ts.map +1 -1
  35. package/src/generation/foliage/config/BarkMaterialConfig.js +6 -6
  36. package/src/generation/foliage/config/FoliageBarkType.d.ts +11 -0
  37. package/src/generation/foliage/config/FoliageBarkType.d.ts.map +1 -0
  38. package/src/generation/foliage/config/FoliageBarkType.js +16 -0
  39. package/src/generation/foliage/config/FoliageMaterialConfig.d.ts +58 -5
  40. package/src/generation/foliage/config/FoliageMaterialConfig.d.ts.map +1 -1
  41. package/src/generation/foliage/config/FoliageMaterialConfig.js +279 -181
  42. package/src/generation/foliage/index.d.ts +2 -1
  43. package/src/generation/foliage/index.js +44 -43
  44. package/src/generation/foliage/material/make_bark_material.d.ts.map +1 -1
  45. package/src/generation/foliage/material/make_bark_material.js +23 -95
  46. package/src/generation/foliage/material/make_foliage_material.d.ts +29 -3
  47. package/src/generation/foliage/material/make_foliage_material.d.ts.map +1 -1
  48. package/src/generation/foliage/material/make_foliage_material.js +605 -359
  49. package/src/generation/foliage/mesh/branch_collar_project.d.ts.map +1 -1
  50. package/src/generation/foliage/mesh/branch_collar_project.js +205 -203
  51. package/src/generation/foliage/mesh/foliage_collect_attachments.d.ts +15 -0
  52. package/src/generation/foliage/mesh/foliage_collect_attachments.d.ts.map +1 -1
  53. package/src/generation/foliage/mesh/foliage_collect_attachments.js +569 -502
  54. package/src/generation/foliage/mesh/tree_mesh_build_bark.d.ts.map +1 -1
  55. package/src/generation/foliage/mesh/tree_mesh_build_bark.js +1049 -1047
  56. package/src/generation/foliage/mesh/tree_mesh_build_foliage.d.ts +2 -1
  57. package/src/generation/foliage/mesh/tree_mesh_build_foliage.d.ts.map +1 -1
  58. package/src/generation/foliage/mesh/tree_mesh_build_foliage.js +454 -415
  59. package/src/generation/foliage/presets/make_tree_species_preset.d.ts.map +1 -1
  60. package/src/generation/foliage/presets/make_tree_species_preset.js +870 -837
  61. package/src/generation/foliage/skeleton/crown_envelope_evaluate.js +121 -121
  62. package/src/generation/foliage/skeleton/tree_skeleton_compute_pipe_radii.d.ts +10 -7
  63. package/src/generation/foliage/skeleton/tree_skeleton_compute_pipe_radii.d.ts.map +1 -1
  64. package/src/generation/foliage/skeleton/tree_skeleton_compute_pipe_radii.js +206 -179
  65. package/src/generation/foliage/skeleton/tree_skeleton_grow.d.ts.map +1 -1
  66. package/src/generation/foliage/skeleton/tree_skeleton_grow.js +1871 -1104
  67. package/src/shade/playground/foliage_wind/foliage_world.d.ts +6 -0
  68. package/src/shade/playground/foliage_wind/foliage_world.d.ts.map +1 -1
  69. package/src/shade/playground/foliage_wind/foliage_world.js +602 -593
  70. package/src/shade/playground/foliage_wind/index.html +260 -254
  71. package/src/shade/playground/foliage_wind/main.js +275 -263
  72. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
  73. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
  74. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  75. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
  76. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  77. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +1 -1
  78. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +3 -3
  79. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  80. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +350 -294
  81. package/src/shade/renderer/hiz/generate_downsampler_code.d.ts +0 -2
  82. package/src/shade/renderer/hiz/generate_downsampler_code.d.ts.map +1 -1
  83. package/src/shade/renderer/hiz/generate_downsampler_code.js +99 -100
  84. package/src/shade/renderer/hiz/hzb_pick_alignment.d.ts +15 -0
  85. package/src/shade/renderer/hiz/hzb_pick_alignment.d.ts.map +1 -0
  86. package/src/shade/renderer/hiz/hzb_pick_alignment.js +148 -0
  87. package/src/shade/renderer/hiz/hzb_plan_reduction_steps.d.ts +28 -0
  88. package/src/shade/renderer/hiz/hzb_plan_reduction_steps.d.ts.map +1 -0
  89. package/src/shade/renderer/hiz/hzb_plan_reduction_steps.js +58 -0
  90. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts +5 -5
  91. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
  92. package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +57 -67
  93. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts +3 -3
  94. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +1 -1
  95. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.js +111 -112
  96. package/src/shade/renderer/hiz/shader_hzb_spd.d.ts +5 -0
  97. package/src/shade/renderer/hiz/shader_hzb_spd.d.ts.map +1 -0
  98. package/src/shade/renderer/hiz/shader_hzb_spd.js +160 -0
  99. package/src/shade/renderer/light/GPULightCollection.d.ts +8 -0
  100. package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
  101. package/src/shade/renderer/light/GPULightCollection.js +67 -0
  102. package/src/shade/renderer/light/environment/FAR_FIELD_IRRADIANCE_SH_RESOURCE.d.ts +7 -0
  103. package/src/shade/renderer/light/environment/FAR_FIELD_IRRADIANCE_SH_RESOURCE.d.ts.map +1 -0
  104. package/src/shade/renderer/light/environment/FAR_FIELD_IRRADIANCE_SH_RESOURCE.js +13 -0
  105. package/src/shade/renderer/light/environment/shader_project_far_field_irradiance_sh.d.ts +10 -0
  106. package/src/shade/renderer/light/environment/shader_project_far_field_irradiance_sh.d.ts.map +1 -0
  107. package/src/shade/renderer/light/environment/shader_project_far_field_irradiance_sh.js +72 -0
  108. package/src/shade/renderer/light/world_cluster/WORLD_LIGHT_CLUSTER.d.ts +39 -0
  109. package/src/shade/renderer/light/world_cluster/WORLD_LIGHT_CLUSTER.d.ts.map +1 -0
  110. package/src/shade/renderer/light/world_cluster/WORLD_LIGHT_CLUSTER.js +90 -0
  111. package/src/shade/renderer/light/world_cluster/chunk_world_light_cluster_lookup.d.ts +12 -0
  112. package/src/shade/renderer/light/world_cluster/chunk_world_light_cluster_lookup.d.ts.map +1 -0
  113. package/src/shade/renderer/light/world_cluster/chunk_world_light_cluster_lookup.js +56 -0
  114. package/src/shade/renderer/light/world_cluster/graph_build_world_light_clusters.d.ts +31 -0
  115. package/src/shade/renderer/light/world_cluster/graph_build_world_light_clusters.d.ts.map +1 -0
  116. package/src/shade/renderer/light/world_cluster/graph_build_world_light_clusters.js +196 -0
  117. package/src/shade/renderer/light/world_cluster/shader_world_cluster_assign_lights.d.ts +10 -0
  118. package/src/shade/renderer/light/world_cluster/shader_world_cluster_assign_lights.d.ts.map +1 -0
  119. package/src/shade/renderer/light/world_cluster/shader_world_cluster_assign_lights.js +163 -0
  120. package/src/shade/renderer/light/world_cluster/shader_world_cluster_cull_lights.d.ts +4 -0
  121. package/src/shade/renderer/light/world_cluster/shader_world_cluster_cull_lights.d.ts.map +1 -0
  122. package/src/shade/renderer/light/world_cluster/shader_world_cluster_cull_lights.js +137 -0
  123. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  124. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  125. package/src/shade/renderer/particles/GPUParticleSystem.js +4 -3
  126. package/src/shade/renderer/particles/graph_particles_avboit.d.ts +4 -3
  127. package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
  128. package/src/shade/renderer/particles/graph_particles_avboit.js +28 -11
  129. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts +9 -13
  130. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts.map +1 -1
  131. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.js +25 -20
  132. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.d.ts.map +1 -1
  133. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js +21 -38
  134. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  135. package/src/shade/renderer/shader/chunk/depth/chunk_query_depth_from_screen_space_bb.d.ts.map +1 -1
  136. package/src/shade/renderer/shader/chunk/depth/chunk_query_depth_from_screen_space_bb.js +62 -62
  137. package/src/shade/renderer/shader/chunk/random/lowbias/chunk_hash_lowbias32_vec2u.d.ts +6 -0
  138. package/src/shade/renderer/shader/chunk/random/lowbias/chunk_hash_lowbias32_vec2u.d.ts.map +1 -0
  139. package/src/shade/renderer/shader/chunk/random/lowbias/chunk_hash_lowbias32_vec2u.js +19 -0
  140. package/src/shade/renderer/shader/chunk/screen_space/chunk_ffx_sssr_get_mip_resolution.d.ts.map +1 -1
  141. package/src/shade/renderer/shader/chunk/screen_space/chunk_ffx_sssr_get_mip_resolution.js +16 -10
  142. package/src/shade/renderer/shader/chunk/screen_space/chunk_ffx_sssr_hierarchical_raymarch.d.ts.map +1 -1
  143. package/src/shade/renderer/shader/chunk/screen_space/chunk_ffx_sssr_hierarchical_raymarch.js +118 -117
  144. package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.d.ts +41 -7
  145. package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.d.ts.map +1 -1
  146. package/src/shade/renderer/texture/atlas/GPUTileAtlas3D.js +162 -58
  147. package/src/shade/renderer/volumetrics/GPUSceneVolumetrics.js +1 -1
  148. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts +10 -12
  149. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
  150. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +583 -606
  151. package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_sample.d.ts +24 -0
  152. package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_sample.d.ts.map +1 -0
  153. package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi_sample.d.ts.map +1 -1
  154. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +1 -1
  155. package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +640 -640
  156. package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts +113 -0
  157. package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts.map +1 -0
  158. package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.js +484 -0
  159. package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP.d.ts +50 -0
  160. package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP.d.ts.map +1 -0
  161. package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP.js +60 -0
  162. package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP_STRUCT.d.ts +25 -0
  163. package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP_STRUCT.d.ts.map +1 -0
  164. package/src/shade/renderer/volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP_STRUCT.js +47 -0
  165. package/src/shade/renderer/volumetrics/irradiance_clipmap/IrradianceCascadePlacement.d.ts +74 -0
  166. package/src/shade/renderer/volumetrics/irradiance_clipmap/IrradianceCascadePlacement.d.ts.map +1 -0
  167. package/src/shade/renderer/volumetrics/irradiance_clipmap/IrradianceCascadePlacement.js +173 -0
  168. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.d.ts +26 -0
  169. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.d.ts.map +1 -0
  170. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.js +83 -0
  171. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_local_light.d.ts +31 -0
  172. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_local_light.d.ts.map +1 -0
  173. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_local_light.js +113 -0
  174. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_sample.d.ts +121 -0
  175. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_sample.d.ts.map +1 -0
  176. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_sample.js +356 -0
  177. package/src/shade/renderer/volumetrics/irradiance_clipmap/shader_irradiance_clipmap_build.d.ts +16 -0
  178. package/src/shade/renderer/volumetrics/irradiance_clipmap/shader_irradiance_clipmap_build.d.ts.map +1 -0
  179. package/src/shade/renderer/volumetrics/irradiance_clipmap/shader_irradiance_clipmap_build.js +191 -0
  180. package/src/shade/renderer/volumetrics/shader_volumetrics_classify_froxels.d.ts +16 -0
  181. package/src/shade/renderer/volumetrics/shader_volumetrics_classify_froxels.d.ts.map +1 -0
  182. package/src/shade/renderer/volumetrics/shader_volumetrics_lighting_regimes.d.ts +23 -0
  183. package/src/shade/renderer/volumetrics/shader_volumetrics_lighting_regimes.d.ts.map +1 -0
  184. package/src/shade/renderer/wind/GPUSceneWind.d.ts +1 -1
  185. package/src/shade/renderer/wind/GPUSceneWind.js +1 -1
  186. package/src/engine/graphics3/decal/DecalAtlasFill.js +0 -32
  187. package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_froxel_centre_ws.js +0 -49
  188. package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi.js +0 -50
  189. package/src/shade/renderer/volumetrics/gi/chunk_volumetrics_gi_sample.js +0 -105
  190. package/src/shade/renderer/volumetrics/gi/graph_build_froxel_gi.js +0 -80
  191. package/src/shade/renderer/volumetrics/gi/shader_volumetrics_gi.js +0 -51
  192. package/src/shade/renderer/volumetrics/gi/volumetrics_gi_resources.js +0 -39
  193. package/src/shade/renderer/volumetrics/graph_build_froxel_irradiance.js +0 -121
  194. package/src/shade/renderer/volumetrics/shader_volumetrics_build_irradiance.js +0 -237
@@ -0,0 +1,163 @@
1
+ import { COLLECTION_U32_STRUCT_READ } from "../../gpu_primitive/COLLECTION_U32_STRUCT_READ.js";
2
+ import { COLLECTION_U32_STRUCT_WRITE } from "../../gpu_primitive/COLLECTION_U32_STRUCT_WRITE.js";
3
+ import { chunk_grid3d_to_index } from "../../shader/chunk/grid/chunk_grid3d_to_index.js";
4
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
5
+ import { ComputeShader } from "../../shader/ComputeShader.js";
6
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
7
+ import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
8
+ import { IRRADIANCE_CLIPMAP_TILE_BORDER } from "../../volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP.js";
9
+ import { IRRADIANCE_CLIPMAP_STRUCT } from "../../volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP_STRUCT.js";
10
+ import { chunk_light_cluster_counts } from "../cluster/chunk_light_cluster_counts.js";
11
+ import { CLUSTER_LIGHT_PROXY } from "../cluster/CLUSTER_LIGHT_PROXY.js";
12
+ import { chunk_cluster_light_tuple } from "../cluster/CLUSTER_LIGHT_TYPE.js";
13
+ import { LIGHT_CLUSTER_METADATA } from "../cluster/LIGHT_CLUSTER_METADATA.js";
14
+ import { LIGHT_CLUSTER_LOOKUP_STRUCT } from "../cluster/shader_cluster_assign_lights.js";
15
+ import {
16
+ chunk_world_cluster_aabb,
17
+ WORLD_LIGHT_CLUSTER_GRID_SIZE,
18
+ WORLD_LIGHT_CLUSTER_MAX_LIGHTS_PER_CELL,
19
+ } from "./WORLD_LIGHT_CLUSTER.js";
20
+
21
+ export const WORLD_CLUSTER_ASSIGN_WORKGROUP_SIZE = Object.freeze([4, 4, 4]);
22
+ const BATCH_SIZE = 64;
23
+ const MAX_PER_TYPE = WORLD_LIGHT_CLUSTER_MAX_LIGHTS_PER_CELL >>> 1;
24
+
25
+ const resources = new ShaderResourceSetDescriptor();
26
+
27
+ resources.createGroup()
28
+ .addUniform("irradiance_clipmap", IRRADIANCE_CLIPMAP_STRUCT)
29
+ .addStorageBuffer("culled_lights", COLLECTION_U32_STRUCT_READ, false)
30
+ .addStorageBuffer("proxies", WebGPUArray.from(CLUSTER_LIGHT_PROXY), false)
31
+ .addStorageBuffer("world_cluster_lookup", LIGHT_CLUSTER_LOOKUP_STRUCT, true)
32
+ .addStorageBuffer("world_cluster_data", COLLECTION_U32_STRUCT_WRITE, true);
33
+
34
+ const body = CodeChunk.from(
35
+ //language=WGSL
36
+ `
37
+ const GRID_SIZE: u32 = ${WORLD_LIGHT_CLUSTER_GRID_SIZE}u;
38
+ const BATCH_SIZE: u32 = ${BATCH_SIZE}u;
39
+ const MAX_PER_TYPE: u32 = ${MAX_PER_TYPE}u;
40
+ const BORDER: f32 = ${IRRADIANCE_CLIPMAP_TILE_BORDER}.0;
41
+
42
+ var<workgroup> shared_tuples: array<u32, ${BATCH_SIZE}>;
43
+ var<workgroup> shared_proxies: array<${CLUSTER_LIGHT_PROXY.wgsl_ref}, ${BATCH_SIZE}>;
44
+
45
+ @compute @workgroup_size(4, 4, 4)
46
+ fn main(
47
+ @builtin(global_invocation_id) global_id: vec3<u32>,
48
+ @builtin(local_invocation_index) local_index: u32,
49
+ ) {
50
+ let cascade = global_id.z / GRID_SIZE;
51
+ let cell = vec3<u32>(global_id.x, global_id.y, global_id.z % GRID_SIZE);
52
+ let valid_cell = cascade < irradiance_clipmap.cascade_count && all(cell < vec3<u32>(GRID_SIZE));
53
+
54
+ var cell_lo = vec3<f32>(0.0);
55
+ var cell_hi = vec3<f32>(0.0);
56
+
57
+ if (valid_cell) {
58
+ let level = irradiance_clipmap.levels[cascade];
59
+ let box_min = (vec3<f32>(level.corner) - vec3<f32>(BORDER)) * level.cell_size;
60
+ let cluster_cell_size = (vec3<f32>(level.size) + vec3<f32>(2.0 * BORDER)) * (level.cell_size / f32(GRID_SIZE));
61
+ let base_lo = box_min + vec3<f32>(cell) * cluster_cell_size;
62
+ let half_voxel = vec3<f32>(0.5 * level.cell_size);
63
+ cell_lo = base_lo - half_voxel;
64
+ cell_hi = base_lo + cluster_cell_size + half_voxel;
65
+ }
66
+
67
+ var point_ids: array<u32, ${MAX_PER_TYPE}>;
68
+ var spot_ids: array<u32, ${MAX_PER_TYPE}>;
69
+ var point_count = 0u;
70
+ var spot_count = 0u;
71
+
72
+ let total_lights = min(culled_lights.count, u32(arrayLength(&proxies)));
73
+
74
+ for (var base = 0u; base < total_lights; base += BATCH_SIZE) {
75
+ let idx = base + local_index;
76
+ if (idx < total_lights) {
77
+ shared_tuples[local_index] = culled_lights.elements[idx];
78
+ shared_proxies[local_index] = proxies[idx];
79
+ }
80
+ workgroupBarrier();
81
+
82
+ if (valid_cell) {
83
+ let batch_count = min(BATCH_SIZE, total_lights - base);
84
+ for (var i = 0u; i < batch_count; i++) {
85
+ let tuple = shared_tuples[i];
86
+ let proxy = shared_proxies[i];
87
+ let light_type = cluster_light_tuple_type(tuple);
88
+ let light_id = cluster_light_tuple_id(tuple);
89
+
90
+ if (light_type == CLUSTER_LIGHT_TYPE_POINT) {
91
+ if (point_count < MAX_PER_TYPE) {
92
+ if (proxy.unbounded != 0u || world_cluster_sphere_intersects_aabb(proxy.bound.xyz, proxy.bound.w, cell_lo, cell_hi)) {
93
+ point_ids[point_count] = light_id;
94
+ point_count++;
95
+ }
96
+ }
97
+ } else {
98
+ if (spot_count < MAX_PER_TYPE) {
99
+ if (proxy.unbounded != 0u || world_cluster_cone_intersects_aabb(proxy, cell_lo, cell_hi)) {
100
+ spot_ids[spot_count] = light_id;
101
+ spot_count++;
102
+ }
103
+ }
104
+ }
105
+ }
106
+ }
107
+
108
+ workgroupBarrier();
109
+ }
110
+
111
+ if (!valid_cell) {
112
+ return;
113
+ }
114
+
115
+ let cluster_index = grid3d_to_index(vec3<u32>(cell.xy, cascade * GRID_SIZE + cell.z), vec2<u32>(GRID_SIZE));
116
+ let total_assigned = point_count + spot_count;
117
+ var offset = 0u;
118
+
119
+ if (total_assigned > 0u) {
120
+ let capacity = u32(arrayLength(&world_cluster_data.elements));
121
+ let raw_offset = atomicAdd(&world_cluster_data.count, total_assigned);
122
+ if (raw_offset + total_assigned <= capacity) {
123
+ offset = raw_offset;
124
+ for (var p = 0u; p < point_count; p++) {
125
+ world_cluster_data.elements[offset + p] = point_ids[p];
126
+ }
127
+ for (var s = 0u; s < spot_count; s++) {
128
+ world_cluster_data.elements[offset + point_count + s] = spot_ids[s];
129
+ }
130
+ } else {
131
+ point_count = 0u;
132
+ spot_count = 0u;
133
+ }
134
+ }
135
+
136
+ world_cluster_lookup[cluster_index] = ${LIGHT_CLUSTER_METADATA.make({
137
+ // +4u because COLLECTION_U32_STRUCT_WRITE aligns `elements` to 16 bytes (4 u32 words)
138
+ offset: "offset + 4u",
139
+ counts: "light_cluster_pack_counts(point_count, spot_count)",
140
+ })};
141
+ }
142
+ `, [
143
+ IRRADIANCE_CLIPMAP_STRUCT.declaration_chunk,
144
+ CLUSTER_LIGHT_PROXY.declaration_chunk,
145
+ LIGHT_CLUSTER_METADATA.declaration_chunk,
146
+ chunk_grid3d_to_index,
147
+ chunk_world_cluster_aabb,
148
+ chunk_cluster_light_tuple,
149
+ chunk_light_cluster_counts,
150
+ ]
151
+ );
152
+
153
+ /**
154
+ * Assigns world-space culled point and spot lights to the `8 × 8 × 8` cluster cells of each
155
+ * cascade of the world-space irradiance clipmap.
156
+ *
157
+ * @type {ComputeShader}
158
+ */
159
+ export const shader_world_cluster_assign_lights = ComputeShader.from({
160
+ label: "World cluster / assign lights",
161
+ resources,
162
+ body,
163
+ });
@@ -0,0 +1,4 @@
1
+ export const shader_world_cluster_cull_point_lights: ComputeShader;
2
+ export const shader_world_cluster_cull_spot_lights: ComputeShader;
3
+ import { ComputeShader } from "../../shader/ComputeShader.js";
4
+ //# sourceMappingURL=shader_world_cluster_cull_lights.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader_world_cluster_cull_lights.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/light/world_cluster/shader_world_cluster_cull_lights.js"],"names":[],"mappings":"AAwHA,mEAOG;AAEH,kEAOG;8BAtI2B,+BAA+B"}
@@ -0,0 +1,137 @@
1
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
2
+ import { COMPUTE_SHADER_DEFAULT_GROUP_SIZE } from "../../shader/COMPUTE_SHADER_DEFAULT_GROUP_SIZE.js";
3
+ import { ComputeShader } from "../../shader/ComputeShader.js";
4
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
5
+ import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
6
+ import { chunk_point_lights_iterate } from "../../shader/chunk/light/io/chunk_point_lights_iterate.js";
7
+ import { chunk_spot_lights_iterate } from "../../shader/chunk/light/io/chunk_spot_lights_iterate.js";
8
+ import { SUBGROUP_APPEND_NONE } from "../../shader/chunk/subgroup/chunk_subgroup_append_slot.js";
9
+ import { LIGHT_DATABASE_SPEC } from "../LIGHT_DATABASE_SPEC.js";
10
+ import { chunk_collection_u32_append } from "../../gpu_primitive/chunk_collection_u32_append.js";
11
+ import { COLLECTION_U32_STRUCT_WRITE } from "../../gpu_primitive/COLLECTION_U32_STRUCT_WRITE.js";
12
+ import { chunk_cluster_light_proxy } from "../cluster/chunk_cluster_light_proxy.js";
13
+ import { CLUSTER_LIGHT_PROXY, CLUSTER_LIGHT_PROXY_UNBOUNDED_RADIUS } from "../cluster/CLUSTER_LIGHT_PROXY.js";
14
+ import { CLUSTER_LIGHT_TYPE, chunk_cluster_light_tuple } from "../cluster/CLUSTER_LIGHT_TYPE.js";
15
+ import { chunk_world_cluster_aabb, WORLD_LIGHT_CLUSTER_CULL_SETTINGS } from "./WORLD_LIGHT_CLUSTER.js";
16
+
17
+ const POINT_DESCRIPTOR = LIGHT_DATABASE_SPEC.get("light_point");
18
+ const SPOT_DESCRIPTOR = LIGHT_DATABASE_SPEC.get("light_spot");
19
+
20
+ const WORKGROUP_SIZE = COMPUTE_SHADER_DEFAULT_GROUP_SIZE;
21
+
22
+ function build_world_cull_shader({
23
+ label,
24
+ prefix_upper,
25
+ prefix_lower,
26
+ iterate_chunk,
27
+ read_chunk,
28
+ is_spot,
29
+ }) {
30
+ const resources = new ShaderResourceSetDescriptor();
31
+
32
+ resources.createGroup()
33
+ .addUniform("settings", WORLD_LIGHT_CLUSTER_CULL_SETTINGS)
34
+ .addStorageBuffer("light_data", WebGPUArray.u32, false)
35
+ .addStorageBuffer("output_list", COLLECTION_U32_STRUCT_WRITE, true)
36
+ .addStorageBuffer("proxies", WebGPUArray.from(CLUSTER_LIGHT_PROXY), true);
37
+
38
+ const build_proxy_wgsl = is_spot
39
+ ? /* language=WGSL */ `
40
+ let light = ${SPOT_DESCRIPTOR.marshalling_method_read}(&light_data, light_index);
41
+ let apex = light.position;
42
+ let direction = normalize(light.direction);
43
+ let height = light.distance + light.radius;
44
+ proxy.apex_height = vec4<f32>(apex, height);
45
+ proxy.direction_cos = vec4<f32>(direction, light.coneCos);
46
+ proxy.source_radius = light.radius;
47
+ if (light.distance <= 0.0) {
48
+ proxy.unbounded = 1u;
49
+ proxy.bound = vec4<f32>(apex, ${CLUSTER_LIGHT_PROXY_UNBOUNDED_RADIUS.toExponential()});
50
+ } else {
51
+ proxy.bound = cluster_spot_bound(apex, direction, height, light.coneCos, light.radius);
52
+ }
53
+ want = proxy.unbounded != 0u || world_cluster_cone_intersects_aabb(proxy, settings.coarsest_min, settings.coarsest_max);
54
+ `
55
+ : /* language=WGSL */ `
56
+ let light = ${POINT_DESCRIPTOR.marshalling_method_read}(&light_data, light_index);
57
+ let radius = select(light.radius + light.distance, ${CLUSTER_LIGHT_PROXY_UNBOUNDED_RADIUS.toExponential()}, light.distance <= 0.0);
58
+ proxy.unbounded = select(0u, 1u, light.distance <= 0.0);
59
+ proxy.bound = vec4<f32>(light.position, radius);
60
+ proxy.source_radius = light.radius;
61
+ want = proxy.unbounded != 0u || world_cluster_sphere_intersects_aabb(proxy.bound.xyz, proxy.bound.w, settings.coarsest_min, settings.coarsest_max);
62
+ `;
63
+
64
+ const cluster_type = is_spot ? CLUSTER_LIGHT_TYPE.Spot : CLUSTER_LIGHT_TYPE.Point;
65
+
66
+ const body = CodeChunk.from(
67
+ //language=WGSL
68
+ `
69
+ @compute @workgroup_size(${WORKGROUP_SIZE}, 1, 1)
70
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
71
+ if (settings.cascade_count == 0u) {
72
+ return;
73
+ }
74
+
75
+ let id = global_id.x;
76
+ let page_index = id / ${prefix_upper}_ELEMENTS_PER_PAGE;
77
+ let in_page_slot = id % ${prefix_upper}_ELEMENTS_PER_PAGE;
78
+
79
+ var want = false;
80
+ var light_index = 0u;
81
+ var proxy: ${CLUSTER_LIGHT_PROXY.wgsl_ref};
82
+
83
+ if (page_index < ${prefix_upper}_PAGE_LIMIT) {
84
+ let page_address = ${prefix_lower}_page_address(&light_data, page_index);
85
+ if (page_address != ~0u) {
86
+ let word_index = in_page_slot >> 5u;
87
+ let bit = in_page_slot & 31u;
88
+ let bitmap_word = ${prefix_lower}_page_bitmap_word(&light_data, page_address, word_index);
89
+ if ((bitmap_word & (1u << bit)) != 0u) {
90
+ light_index = ${prefix_lower}_slot_to_index(page_index, in_page_slot);
91
+ ${build_proxy_wgsl}
92
+ }
93
+ }
94
+ }
95
+
96
+ let capacity = min(u32(arrayLength(&output_list.elements)), u32(arrayLength(&proxies)));
97
+ let tuple = cluster_light_tuple_pack(light_index, ${cluster_type}u);
98
+ let slot = collection_u32_append(&output_list, want, tuple, capacity);
99
+ if (slot != ${SUBGROUP_APPEND_NONE}u) {
100
+ proxies[slot] = proxy;
101
+ }
102
+ }
103
+ `, [
104
+ CLUSTER_LIGHT_PROXY.declaration_chunk,
105
+ chunk_cluster_light_proxy,
106
+ chunk_world_cluster_aabb,
107
+ chunk_cluster_light_tuple,
108
+ chunk_collection_u32_append,
109
+ iterate_chunk,
110
+ read_chunk,
111
+ ]
112
+ );
113
+
114
+ return ComputeShader.from({
115
+ label,
116
+ resources,
117
+ body,
118
+ });
119
+ }
120
+
121
+ export const shader_world_cluster_cull_point_lights = build_world_cull_shader({
122
+ label: "World cluster / cull point lights",
123
+ prefix_upper: "POINT_LIGHTS",
124
+ prefix_lower: "point_lights",
125
+ iterate_chunk: chunk_point_lights_iterate,
126
+ read_chunk: POINT_DESCRIPTOR.chunk_read,
127
+ is_spot: false,
128
+ });
129
+
130
+ export const shader_world_cluster_cull_spot_lights = build_world_cull_shader({
131
+ label: "World cluster / cull spot lights",
132
+ prefix_upper: "SPOT_LIGHTS",
133
+ prefix_lower: "spot_lights",
134
+ iterate_chunk: chunk_spot_lights_iterate,
135
+ read_chunk: SPOT_DESCRIPTOR.chunk_read,
136
+ is_spot: true,
137
+ });
@@ -13,7 +13,7 @@ export class TinyGltf {
13
13
  * @readonly
14
14
  * @type {TextureFormat}
15
15
  */
16
- static readonly "__#287@#UNCOMPRESSED_TARGET": TextureFormat;
16
+ static readonly "__#289@#UNCOMPRESSED_TARGET": TextureFormat;
17
17
  /**
18
18
  * @param {AssetManager} assetManager
19
19
  * @param {AssetRequestScope} [scope]
@@ -1 +1 @@
1
- {"version":3,"file":"GPUParticleSystem.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/particles/GPUParticleSystem.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"GPUParticleSystem.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/particles/GPUParticleSystem.js"],"names":[],"mappings":"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"}
@@ -56,7 +56,7 @@ const STORAGE_GROWABLE = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUB
56
56
  */
57
57
  const INDIRECT = GPUBufferUsage.STORAGE | GPUBufferUsage.INDIRECT | GPUBufferUsage.COPY_SRC;
58
58
 
59
- const DEFAULT_CAPACITY = 131072;
59
+ const DEFAULT_CAPACITY = 65536;
60
60
 
61
61
  /**
62
62
  * What {@link GPUParticleSystem#read_stats} decodes: the counts the GPU keeps between frames, named.
@@ -618,6 +618,7 @@ export class GPUParticleSystem {
618
618
  const { handles } = this.#simulated_for(graph);
619
619
 
620
620
  return graph_particle_avboit_draw({
621
+ scene_context: this.scene_context,
621
622
  graph,
622
623
  view_ctx,
623
624
  camera,
@@ -1120,8 +1121,8 @@ export class GPUParticleSystem {
1120
1121
  this.atlas_sampler = device.createSampler({
1121
1122
  label: "particles/atlas_sampler",
1122
1123
  magFilter: "linear",
1123
- minFilter: "linear",
1124
- mipmapFilter: "linear",
1124
+ minFilter: "linear",
1125
+ mipmapFilter: "linear",
1125
1126
  maxAnisotropy: 16,
1126
1127
  addressModeU: "clamp-to-edge",
1127
1128
  addressModeV: "clamp-to-edge",
@@ -70,8 +70,8 @@ export function graph_particle_avboit_splat({ graph, camera, warp, depth_texture
70
70
  * @param {number} params.integral graph handle of the integral texture
71
71
  * @param {number} params.volumetrics_lut graph handle
72
72
  * @param {number} params.volumetrics_metadata graph handle
73
- * @param {{Y: number, CoCg: number}} params.volumetrics_irradiance graph handles of the froxel
74
- * irradiance volume a lit emitter's particles are lit by
73
+ * @param {{Y: number, CoCg: number, uniform?: number}} params.volumetrics_irradiance graph handles of
74
+ * the world-space irradiance clipmap a lit emitter's particles are lit by
75
75
  * @param {{color: number, norm: number, extinction: number, emission: number}} params.accumulators to add to
76
76
  * @param {GPUTextureView} params.atlas
77
77
  * @param {GPUSampler} params.atlas_sampler
@@ -81,7 +81,7 @@ export function graph_particle_avboit_splat({ graph, camera, warp, depth_texture
81
81
  * @param {number} params.draw_args graph handle of the indirect draw args
82
82
  * @returns {{color: number, norm: number, extinction: number, emission: number}} the accumulators after the draw
83
83
  */
84
- export function graph_particle_avboit_draw({ graph, view_ctx, camera, depth_texture, warp, integral, volumetrics_lut, volumetrics_metadata, volumetrics_irradiance, accumulators, atlas, atlas_sampler, pool, alive, emitter_database, draw_args, }: {
84
+ export function graph_particle_avboit_draw({ graph, view_ctx, scene_context, camera, depth_texture, warp, integral, volumetrics_lut, volumetrics_metadata, volumetrics_irradiance, accumulators, atlas, atlas_sampler, pool, alive, emitter_database, draw_args, }: {
85
85
  graph: import("../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
86
86
  view_ctx: import("../view/GPUViewContext.js").GPUViewContext;
87
87
  camera: number;
@@ -93,6 +93,7 @@ export function graph_particle_avboit_draw({ graph, view_ctx, camera, depth_text
93
93
  volumetrics_irradiance: {
94
94
  Y: number;
95
95
  CoCg: number;
96
+ uniform?: number;
96
97
  };
97
98
  accumulators: {
98
99
  color: number;
@@ -1 +1 @@
1
- {"version":3,"file":"graph_particles_avboit.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/particles/graph_particles_avboit.js"],"names":[],"mappings":"AAuCA;;;;;;;;;;;;;;;GAeG;AACH;IARkG,KAAK,EAA5F,OAAO,2DAA2D,EAAE,UAAU;IAC/D,MAAM,EAArB,MAAM;IACoB,kBAAkB,EAA5C,UAAU,MAAM,CAAC;IACF,SAAS,EAAxB,MAAM;IACS,gBAAgB,EAA/B,MAAM;IACS,mBAAmB,EAAlC,MAAM;IACJ,MAAM,CA8ClB;AAED;;;;;;;;;;;;;;;GAeG;AACH;IAZkG,KAAK,EAA5F,OAAO,2DAA2D,EAAE,UAAU;IAC/D,MAAM,EAArB,MAAM;IACS,IAAI,EAAnB,MAAM;IACwD,MAAM,EAApE;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC;IAC9B,KAAK;IACT,aAAa;IACjB,IAAI,EAAnB,MAAM;IACS,KAAK,EAApB,MAAM;IACS,gBAAgB,EAA/B,MAAM;IACS,SAAS,EAAxB,MAAM;IACJ;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CA8EjE;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IAnBkG,KAAK,EAA5F,OAAO,2DAA2D,EAAE,UAAU;IACnB,QAAQ,EAAnE,OAAO,2BAA2B,EAAE,cAAc;IACnC,MAAM,EAArB,MAAM;IACS,aAAa,EAA5B,MAAM;IACS,IAAI,EAAnB,MAAM;IACS,QAAQ,EAAvB,MAAM;IACS,eAAe,EAA9B,MAAM;IACS,oBAAoB,EAAnC,MAAM;IAC4B,sBAAsB,EAAxD;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC;IAEmD,YAAY,EAAxF;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC;IAC5C,KAAK;IACT,aAAa;IACjB,IAAI,EAAnB,MAAM;IACS,KAAK,EAApB,MAAM;IACS,gBAAgB,EAA/B,MAAM;IACS,SAAS,EAAxB,MAAM;IACJ;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,CAkH/E"}
1
+ {"version":3,"file":"graph_particles_avboit.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/particles/graph_particles_avboit.js"],"names":[],"mappings":"AA2CA;;;;;;;;;;;;;;;GAeG;AACH;IARkG,KAAK,EAA5F,OAAO,2DAA2D,EAAE,UAAU;IAC/D,MAAM,EAArB,MAAM;IACoB,kBAAkB,EAA5C,UAAU,MAAM,CAAC;IACF,SAAS,EAAxB,MAAM;IACS,gBAAgB,EAA/B,MAAM;IACS,mBAAmB,EAAlC,MAAM;IACJ,MAAM,CA8ClB;AAED;;;;;;;;;;;;;;;GAeG;AACH;IAZkG,KAAK,EAA5F,OAAO,2DAA2D,EAAE,UAAU;IAC/D,MAAM,EAArB,MAAM;IACS,IAAI,EAAnB,MAAM;IACwD,MAAM,EAApE;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC;IAC9B,KAAK;IACT,aAAa;IACjB,IAAI,EAAnB,MAAM;IACS,KAAK,EAApB,MAAM;IACS,gBAAgB,EAA/B,MAAM;IACS,SAAS,EAAxB,MAAM;IACJ;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CA0EjE;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IAnBkG,KAAK,EAA5F,OAAO,2DAA2D,EAAE,UAAU;IACnB,QAAQ,EAAnE,OAAO,2BAA2B,EAAE,cAAc;IACnC,MAAM,EAArB,MAAM;IACS,aAAa,EAA5B,MAAM;IACS,IAAI,EAAnB,MAAM;IACS,QAAQ,EAAvB,MAAM;IACS,eAAe,EAA9B,MAAM;IACS,oBAAoB,EAAnC,MAAM;IAC8C,sBAAsB,EAA1E;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC;IAEiC,YAAY,EAAxF;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC;IAC5C,KAAK;IACT,aAAa;IACjB,IAAI,EAAnB,MAAM;IACS,KAAK,EAApB,MAAM;IACS,gBAAgB,EAA/B,MAAM;IACS,SAAS,EAAxB,MAAM;IACJ;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,CAmI/E"}
@@ -3,14 +3,18 @@ import { SamplerDescriptor } from "../../descriptor/texture/SamplerDescriptor.js
3
3
  import { TextureViewDescriptor } from "../../descriptor/texture/TextureViewDescriptor.js";
4
4
  import { DEFAULT_DEPTH_TEXTURE_VIEW } from "../depth/DEFAULT_DEPTH_TEXTURE_VIEW.js";
5
5
  import { AVBOIT_OCCUPANCY_SETTINGS_STRUCT } from "../rasterize/native/avboit/shader_avboit_occupancy.js";
6
+ import {
7
+ METRO_L1_IRRADIANCE_STRUCT
8
+ } from "../shader/chunk/spherical_harmonics/l1i/chunk_convert_to_irradiance_sh.js";
6
9
  import { STATIC_GRAPHICS_ENGINE_ASSETS } from "../STATIC_GRAPHICS_ENGINE_ASSETS.js";
7
- import { shader_particle_avboit_occupancy } from "./shaders/shader_particle_avboit_occupancy.js";
10
+ import { IRRADIANCE_CLIPMAP_STRUCT } from "../volumetrics/irradiance_clipmap/IRRADIANCE_CLIPMAP_STRUCT.js";
8
11
  import {
9
- PARTICLE_AVBOIT_DRAW_ALPHA_PIPELINE,
10
12
  PARTICLE_AVBOIT_DRAW_ADDITIVE_PIPELINE,
13
+ PARTICLE_AVBOIT_DRAW_ALPHA_PIPELINE,
11
14
  PARTICLE_AVBOIT_DRAW_GENERAL_PIPELINE,
12
15
  PARTICLE_AVBOIT_DRAW_RESOURCES,
13
16
  } from "./shaders/shader_particle_avboit_draw.js";
17
+ import { shader_particle_avboit_occupancy } from "./shaders/shader_particle_avboit_occupancy.js";
14
18
  import {
15
19
  PARTICLE_AVBOIT_SPLAT_PIPELINE,
16
20
  PARTICLE_AVBOIT_SPLAT_RESOURCES,
@@ -135,10 +139,6 @@ export function graph_particle_avboit_splat({
135
139
  function execute(data, resources, context) {
136
140
  const encoder = context.encoder;
137
141
 
138
- // By name, never by position: the order a shader declares its bindings in is the shader's
139
- // business, and a list built here to match it binds a sampler where a texture goes the
140
- // moment a binding is inserted anywhere but the end. The device rejects that, and only when
141
- // the pass is first encoded on real hardware. See the layout-kind check in the spec.
142
142
  const bindings = PARTICLE_AVBOIT_SPLAT_RESOURCES.generateBindings({
143
143
  camera: resources.get(data.camera),
144
144
  warp: resources.get(data.warp),
@@ -205,8 +205,8 @@ export function graph_particle_avboit_splat({
205
205
  * @param {number} params.integral graph handle of the integral texture
206
206
  * @param {number} params.volumetrics_lut graph handle
207
207
  * @param {number} params.volumetrics_metadata graph handle
208
- * @param {{Y: number, CoCg: number}} params.volumetrics_irradiance graph handles of the froxel
209
- * irradiance volume a lit emitter's particles are lit by
208
+ * @param {{Y: number, CoCg: number, uniform?: number}} params.volumetrics_irradiance graph handles of
209
+ * the world-space irradiance clipmap a lit emitter's particles are lit by
210
210
  * @param {{color: number, norm: number, extinction: number, emission: number}} params.accumulators to add to
211
211
  * @param {GPUTextureView} params.atlas
212
212
  * @param {GPUSampler} params.atlas_sampler
@@ -219,6 +219,7 @@ export function graph_particle_avboit_splat({
219
219
  export function graph_particle_avboit_draw({
220
220
  graph,
221
221
  view_ctx,
222
+ scene_context,
222
223
  camera,
223
224
  depth_texture,
224
225
  warp,
@@ -246,6 +247,16 @@ export function graph_particle_avboit_draw({
246
247
 
247
248
  const t_depth = resources.get(data.depth);
248
249
  const depth_view = t_depth.obtainView(DEFAULT_DEPTH_TEXTURE_VIEW);
250
+ const linear_sampler = graphics.samplers.obtain(SAMPLER_LINEAR);
251
+
252
+ const irradiance_clipmap_buffer = data.irradiance_uniform !== undefined
253
+ ? resources.get(data.irradiance_uniform)
254
+ : (view_ctx.volumetrics?.irradiance_clipmap?.uniform
255
+ ?? encoder.allocateTransientBuffer(GPUBufferUsage.UNIFORM, IRRADIANCE_CLIPMAP_STRUCT.size));
256
+
257
+ const far_field_sh_buffer = scene_context?.lights?.far_field_irradiance_sh
258
+ ?? view_ctx.scene?.lights?.far_field_irradiance_sh
259
+ ?? encoder.allocateTransientBuffer(GPUBufferUsage.UNIFORM, METRO_L1_IRRADIANCE_STRUCT.aligned_size);
249
260
 
250
261
  // by name rather than by position, for the reason the splat gives
251
262
  const bindings = PARTICLE_AVBOIT_DRAW_RESOURCES.generateBindings({
@@ -259,12 +270,15 @@ export function graph_particle_avboit_draw({
259
270
  atlas_sampler,
260
271
  scene_depth: depth_view,
261
272
  tIntegral: resources.get(data.integral).obtainView(),
262
- sLinear: graphics.samplers.obtain(SAMPLER_LINEAR),
273
+ sLinear: linear_sampler,
263
274
  volumetrics_metadata: resources.get(data.volumetrics_metadata),
264
275
  tVolumetrics: resources.get(data.volumetrics_lut).obtainView(),
265
276
  tSTBN_vec3: graphics.textures.obtain(STATIC_GRAPHICS_ENGINE_ASSETS.stbn_vec3).obtainView(),
266
- tIrradianceY: resources.get(data.irradiance_Y).obtainView(),
267
- tIrradianceCoCg: resources.get(data.irradiance_CoCg).obtainView(),
277
+ irradiance_clipmap: irradiance_clipmap_buffer,
278
+ irradiance_clipmap_atlas_y: resources.get(data.irradiance_Y).obtainView(),
279
+ irradiance_clipmap_atlas_cocg: resources.get(data.irradiance_CoCg).obtainView(),
280
+ irradiance_clipmap_sampler: linear_sampler,
281
+ far_field_irradiance_sh: far_field_sh_buffer,
268
282
  }, encoder);
269
283
 
270
284
  const attachment = (handle) => ({
@@ -312,6 +326,9 @@ export function graph_particle_avboit_draw({
312
326
  pass_data.volumetrics_metadata = pass.read(volumetrics_metadata);
313
327
  pass_data.irradiance_Y = pass.read(volumetrics_irradiance.Y);
314
328
  pass_data.irradiance_CoCg = pass.read(volumetrics_irradiance.CoCg);
329
+ if (volumetrics_irradiance.uniform !== undefined) {
330
+ pass_data.irradiance_uniform = pass.read(volumetrics_irradiance.uniform);
331
+ }
315
332
  pass_data.pool = pass.read(pool);
316
333
  pass_data.alive = pass.read(alive);
317
334
  pass_data.emitter_database = pass.read(emitter_database);
@@ -1,19 +1,15 @@
1
1
  /**
2
2
  * How an emitter flagged `EMITTER_FLAG.LIGHTING` is lit, per fragment:
3
- * `particle_apply_lighting(color, world, normal)` treats the particle's colour as a diffuse albedo and
4
- * returns what it reflects and transmits (`chunk_particle_lighting_model`), from the froxel
5
- * irradiance volume (`chunk_volumetrics_irradiance_sh`) at the fragment: the renderer's indirect
6
- * lighting, whichever mode it runs (the froxel GI stage, `volumetrics/gi/`), plus every directional,
7
- * point and spot light, shadowed, as the surfaces around the particle receive them. One trilinear read of each
8
- * of its two textures, so the cost grows with neither the lights nor the GI; the price is resolution —
9
- * a froxel is 16 pixels across and a slice deep, and light and shadow edges inside a particle are that
10
- * soft.
3
+ * `particle_apply_lighting(color, world_position, normal)` treats the particle's colour as a diffuse
4
+ * albedo and returns what it reflects and transmits (`chunk_particle_lighting_model`), sampled from
5
+ * the world-space irradiance clipmap (`chunk_irradiance_clipmap_sample_with_far_field`):
11
6
  *
12
- * The normal is whatever the vertex stage bent it to (`particle_billboard_normal`), so a camera-facing
13
- * sprite reads as a rounded puff rather than a card.
14
- *
15
- * The enclosing shader binds `camera`, `volumetrics_metadata`, `sLinear`, `tIrradianceY` and
16
- * `tIrradianceCoCg` under those names.
7
+ * - Inside the clipmap cascades, performs a single-cascade stochastic tap using a non-linear
8
+ * `smoothstep` transition across each cascade's blend-skirt (`irradiance_clipmap.blend_skirt`,
9
+ * default `IRRADIANCE_CLIPMAP_DEFAULT_BLEND_SKIRT = 2` voxels), with `random_u` generated via
10
+ * `hash_lowbias32_vec2u` and `hash_to_float01`.
11
+ * - Across the coarsest cascade's blend-skirt and outside all cascades (`CLIPMAP_LEVEL_NONE`),
12
+ * smoothly falls back to `far_field_irradiance_sh` (cached on `GPULightCollection`).
17
13
  *
18
14
  * @type {CodeChunk}
19
15
  */
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_particle_lighting.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/chunk_particle_lighting.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;GAkBG;AACH,sCAFU,SAAS,CAgBZ;0BAvCmB,oCAAoC"}
1
+ {"version":3,"file":"chunk_particle_lighting.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/chunk_particle_lighting.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;GAcG;AACH,sCAFU,SAAS,CAmBZ;0BAvCmB,oCAAoC"}
@@ -1,25 +1,25 @@
1
+ import { chunk_hash_to_float01 } from "../../shader/chunk/random/chunk_hash_to_float01.js";
2
+ import { chunk_hash_lowbias32_vec2u } from "../../shader/chunk/random/lowbias/chunk_hash_lowbias32_vec2u.js";
3
+ import { chunk_hash_lowbias32_vec3u } from "../../shader/chunk/random/lowbias/chunk_hash_lowbias32_vec3u.js";
1
4
  import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
5
+ import { VIEW_RESOURCE } from "../../view/VIEW_RESOURCE.js";
2
6
  import {
3
- volumetrics_position_world_to_froxel_uvw
4
- } from "../../volumetrics/volumetrics_position_world_to_froxel_uvw.js";
7
+ chunk_irradiance_clipmap_sample_with_far_field
8
+ } from "../../volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_sample.js";
5
9
  import { chunk_particle_lighting_model } from "./chunk_particle_lighting_model.js";
6
10
 
7
11
  /**
8
12
  * How an emitter flagged `EMITTER_FLAG.LIGHTING` is lit, per fragment:
9
- * `particle_apply_lighting(color, world, normal)` treats the particle's colour as a diffuse albedo and
10
- * returns what it reflects and transmits (`chunk_particle_lighting_model`), from the froxel
11
- * irradiance volume (`chunk_volumetrics_irradiance_sh`) at the fragment: the renderer's indirect
12
- * lighting, whichever mode it runs (the froxel GI stage, `volumetrics/gi/`), plus every directional,
13
- * point and spot light, shadowed, as the surfaces around the particle receive them. One trilinear read of each
14
- * of its two textures, so the cost grows with neither the lights nor the GI; the price is resolution —
15
- * a froxel is 16 pixels across and a slice deep, and light and shadow edges inside a particle are that
16
- * soft.
13
+ * `particle_apply_lighting(color, world_position, normal)` treats the particle's colour as a diffuse
14
+ * albedo and returns what it reflects and transmits (`chunk_particle_lighting_model`), sampled from
15
+ * the world-space irradiance clipmap (`chunk_irradiance_clipmap_sample_with_far_field`):
17
16
  *
18
- * The normal is whatever the vertex stage bent it to (`particle_billboard_normal`), so a camera-facing
19
- * sprite reads as a rounded puff rather than a card.
20
- *
21
- * The enclosing shader binds `camera`, `volumetrics_metadata`, `sLinear`, `tIrradianceY` and
22
- * `tIrradianceCoCg` under those names.
17
+ * - Inside the clipmap cascades, performs a single-cascade stochastic tap using a non-linear
18
+ * `smoothstep` transition across each cascade's blend-skirt (`irradiance_clipmap.blend_skirt`,
19
+ * default `IRRADIANCE_CLIPMAP_DEFAULT_BLEND_SKIRT = 2` voxels), with `random_u` generated via
20
+ * `hash_lowbias32_vec2u` and `hash_to_float01`.
21
+ * - Across the coarsest cascade's blend-skirt and outside all cascades (`CLIPMAP_LEVEL_NONE`),
22
+ * smoothly falls back to `far_field_irradiance_sh` (cached on `GPULightCollection`).
23
23
  *
24
24
  * @type {CodeChunk}
25
25
  */
@@ -27,14 +27,19 @@ export const chunk_particle_lighting = CodeChunk.from(
27
27
  /* language=wgsl */
28
28
  `
29
29
  fn particle_apply_lighting(color : vec4<f32>, world_position : vec3<f32>, normal : vec3<f32>) -> vec4<f32> {
30
- let uvw = volumetrics_position_world_to_froxel_uvw(world_position);
30
+ let pos_hash = hash_lowbias32_vec3u(bitcast<vec3<u32>>(world_position));
31
+ let random_u = hash_to_float01(hash_lowbias32_vec2u(vec2<u32>(pos_hash, view.frame_index)));
31
32
 
32
- let sh_Y = textureSampleLevel(tIrradianceY, sLinear, uvw, 0.0);
33
- let sh_CoCg = textureSampleLevel(tIrradianceCoCg, sLinear, uvw, 0.0).xy;
33
+ let sh = irradiance_clipmap_sample_with_far_field(world_position, random_u);
34
34
 
35
- return particle_lit(color, sh_Y, sh_CoCg, normal);
35
+ return particle_lit(color, sh.Y, sh.CoCg, normal);
36
36
  }
37
37
  `, [
38
- volumetrics_position_world_to_froxel_uvw,
38
+ chunk_hash_lowbias32_vec3u,
39
+ chunk_hash_lowbias32_vec2u,
40
+ chunk_hash_to_float01,
41
+ chunk_irradiance_clipmap_sample_with_far_field,
39
42
  chunk_particle_lighting_model,
40
43
  ]);
44
+
45
+ chunk_particle_lighting.requireResource(VIEW_RESOURCE);
@@ -1 +1 @@
1
- {"version":3,"file":"shader_particle_avboit_draw.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js"],"names":[],"mappings":"AAyMA,2EAAsI;AACtI,8EAA2I;AAC3I,6EAA8I;AAE9I,mEAAmE;AACnE,yEAAwD;AAExD,mDAAmD;AACnD,2DAAsD;yCAjNb,iEAAiE;4CAa9D,sDAAsD;iCAFjE,kCAAkC"}
1
+ {"version":3,"file":"shader_particle_avboit_draw.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js"],"names":[],"mappings":"AAwLA,2EAAsI;AACtI,8EAA2I;AAC3I,6EAA8I;AAE9I,mEAAmE;AACnE,yEAAwD;AAExD,mDAAmD;AACnD,2DAAsD;yCA/Lb,iEAAiE;4CAU9D,sDAAsD;iCACjE,kCAAkC"}