@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
@@ -1,83 +1,110 @@
1
- import { AbstractTextureAtlas } from "./AbstractTextureAtlas.js";
2
- import { Reference } from "../../../reference/v2/Reference.js";
3
-
4
- export class ReferencedTextureAtlas extends AbstractTextureAtlas {
5
- /**
6
- *
7
- * @type {Map<Sampler2D, AtlasPatch>}
8
- * @private
9
- */
10
- __patches = new Map();
11
-
12
- /**
13
- *
14
- * @type {Map<AtlasPatch, number>}
15
- * @private
16
- */
17
- __ref_counts = new Map();
18
-
19
- /**
20
- *
21
- * @param {AbstractTextureAtlas} atlas
22
- */
23
- constructor(atlas) {
24
- super();
25
-
26
- this.__atlas = atlas;
27
- }
28
-
29
- update() {
30
- this.__atlas.update();
31
- }
32
-
33
- /**
34
- *
35
- * @param {Reference} ref
36
- * @param {AtlasPatch} patch
37
- * @private
38
- */
39
- __handle_ref_release(ref, patch) {
40
- const ref_counts = this.__ref_counts;
41
-
42
- const ref_count = ref_counts.get(patch);
43
- ref_counts.set(patch, ref_count - 1);
44
-
45
- if (ref_count === 1) {
46
- // last reference removed, clear patch
47
- this.__atlas.remove(patch);
48
- ref_counts.delete(patch);
49
- this.__patches.delete(patch.sampler);
50
- }
51
- }
52
-
53
-
54
- /**
55
- *
56
- * @param {Sampler2D} sampler
57
- * @returns {Reference<AtlasPatch>}
58
- */
59
- acquire(sampler) {
60
-
61
- let patch = this.__patches.get(sampler);
62
-
63
- const ref_counts = this.__ref_counts;
64
-
65
- const atlas = this.__atlas;
66
-
67
- if (patch === undefined) {
68
- patch = atlas.add(sampler);
69
- ref_counts.set(patch, 1)
70
-
71
- this.__patches.set(sampler, patch);
72
- } else {
73
- ref_counts.set(patch, ref_counts.get(patch) + 1);
74
- }
75
-
76
- const ref = new Reference();
77
- ref.bind(patch);
78
-
79
- ref.onReleased.add(this.__handle_ref_release, this);
80
-
81
- return ref;
82
- }
83
- }
1
+ import { AbstractTextureAtlas } from "./AbstractTextureAtlas.js";
2
+ import { Reference } from "../../../reference/v2/Reference.js";
3
+
4
+ export class ReferencedTextureAtlas extends AbstractTextureAtlas {
5
+ /**
6
+ *
7
+ * @type {Map<Sampler2D, AtlasPatch>}
8
+ * @private
9
+ */
10
+ __patches = new Map();
11
+
12
+ /**
13
+ *
14
+ * @type {Map<AtlasPatch, number>}
15
+ * @private
16
+ */
17
+ __ref_counts = new Map();
18
+
19
+ /**
20
+ *
21
+ * @param {AbstractTextureAtlas} atlas
22
+ */
23
+ constructor(atlas) {
24
+ super();
25
+
26
+ this.__atlas = atlas;
27
+ }
28
+
29
+ /**
30
+ * @returns {AbstractTextureAtlas}
31
+ */
32
+ get atlas() {
33
+ return this.__atlas;
34
+ }
35
+
36
+ /**
37
+ * @returns {Sampler2D}
38
+ */
39
+ get sampler() {
40
+ return this.__atlas.sampler;
41
+ }
42
+
43
+ update() {
44
+ this.__atlas.update();
45
+ }
46
+
47
+ reset() {
48
+ this.__patches.clear();
49
+ this.__ref_counts.clear();
50
+
51
+ if (typeof this.__atlas.reset === 'function') {
52
+ this.__atlas.reset();
53
+ }
54
+ }
55
+
56
+ /**
57
+ *
58
+ * @param {Reference} ref
59
+ * @param {AtlasPatch} patch
60
+ * @private
61
+ */
62
+ __handle_ref_release(ref, patch) {
63
+ const ref_counts = this.__ref_counts;
64
+
65
+ const ref_count = ref_counts.get(patch);
66
+ if (ref_count === undefined) {
67
+ return;
68
+ }
69
+
70
+ ref_counts.set(patch, ref_count - 1);
71
+
72
+ if (ref_count === 1) {
73
+ // last reference removed, clear patch
74
+ this.__atlas.remove(patch);
75
+ ref_counts.delete(patch);
76
+ this.__patches.delete(patch.sampler);
77
+ }
78
+ }
79
+
80
+
81
+ /**
82
+ *
83
+ * @param {Sampler2D} sampler
84
+ * @returns {Reference<AtlasPatch>}
85
+ */
86
+ acquire(sampler) {
87
+
88
+ let patch = this.__patches.get(sampler);
89
+
90
+ const ref_counts = this.__ref_counts;
91
+
92
+ const atlas = this.__atlas;
93
+
94
+ if (patch === undefined) {
95
+ patch = atlas.add(sampler);
96
+ ref_counts.set(patch, 1);
97
+
98
+ this.__patches.set(sampler, patch);
99
+ } else {
100
+ ref_counts.set(patch, ref_counts.get(patch) + 1);
101
+ }
102
+
103
+ const ref = new Reference();
104
+ ref.bind(patch);
105
+
106
+ ref.onReleased.add(this.__handle_ref_release, this);
107
+
108
+ return ref;
109
+ }
110
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * A texture atlas whose patches can be **mipmapped without bleeding into each other**.
3
+ *
4
+ * A plain {@link TextureAtlas} reserves padding around each patch but never fills it, leaving a
5
+ * zeroed gutter that every mip level past the first averages against the patch content.
6
+ *
7
+ * Three things fix it, and all three are here: a border sized in proportion to the patch
8
+ * ({@link sprite_atlas_border}), a border that is actually **filled**, by a rule that suits what the
9
+ * channel means ({@link SpriteAtlasFill}), and a per-patch bound on how deep the mip chain may be
10
+ * sampled ({@link sprite_atlas_max_lod}), because no finite border protects every level.
11
+ *
12
+ * Packing, growth, repacking and uv bookkeeping are the base class's and are untouched — it already
13
+ * places content at `packing + padding`, which is the whole geometry of a bordered patch.
14
+ */
15
+ export class SpriteAtlas extends TextureAtlas {
16
+ /**
17
+ * @param {SpriteAtlasFill} fill
18
+ * @param {number} [size] initial edge length; the atlas grows on demand
19
+ */
20
+ constructor(fill: SpriteAtlasFill, size?: number);
21
+ /**
22
+ * @returns {SpriteAtlasFill}
23
+ */
24
+ get fill(): number;
25
+ /**
26
+ * The border is the patch's own size, not the caller's choice — every patch in one atlas has to
27
+ * obey the same rule for {@link sprite_atlas_max_lod}'s "+1 from the neighbour" to hold.
28
+ *
29
+ * @param {import("../sampler/Sampler2D.js").Sampler2D} sampler
30
+ * @returns {number}
31
+ */
32
+ compute_padding(sampler: import("../sampler/Sampler2D.js").Sampler2D): number;
33
+ /**
34
+ * @param {import("../sampler/Sampler2D.js").Sampler2D} sampler
35
+ * @returns {import("./AtlasPatch.js").AtlasPatch}
36
+ */
37
+ add(sampler: import("../sampler/Sampler2D.js").Sampler2D): import("./AtlasPatch.js").AtlasPatch;
38
+ #private;
39
+ }
40
+ import { TextureAtlas } from "./TextureAtlas.js";
41
+ import { SpriteAtlasFill } from "./SpriteAtlasFill.js";
42
+ //# sourceMappingURL=SpriteAtlas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpriteAtlas.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/texture/atlas/SpriteAtlas.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;GAaG;AACH;IAMI;;;OAGG;IACH,kBAHW,eAAe,SACf,MAAM,EAQhB;IAED;;OAEG;IACH,mBAEC;IAED;;;;;;OAMG;IACH,yBAHW,OAAO,yBAAyB,EAAE,SAAS,GACzC,MAAM,CAMlB;IAED;;;OAGG;IACH,aAHW,OAAO,yBAAyB,EAAE,SAAS,GACzC,OAAO,iBAAiB,EAAE,UAAU,CAMhD;;CAsIJ;6BAvM4B,mBAAmB;gCAGhB,sBAAsB"}
@@ -1,194 +1,202 @@
1
- import { assert } from "../../../core/assert.js";
2
- import { BinaryDataType } from "../../../core/binary/type/BinaryDataType.js";
3
- import { TextureAtlas } from "../../graphics/texture/atlas/TextureAtlas.js";
4
- import { AtlasPatchFlag } from "../../graphics/texture/atlas/AtlasPatchFlag.js";
5
- import { decal_atlas_border } from "./decal_atlas_border.js";
6
- import { DecalAtlasFill } from "./DecalAtlasFill.js";
7
-
8
- /**
9
- * A texture atlas whose patches can be **mipmapped without bleeding into each other**.
10
- *
11
- * The atlas this replaces generates mipmaps and reserves padding, and still bleeds: nothing ever
12
- * fills the padding, so the gutter is zeros and every level past the first averages a patch against
13
- * whatever lies beyond it. The workarounds are visible in the shader that reads it — a negative LOD
14
- * bias, and a switch to turn mipmapping off when a scene has many overlapping decals.
15
- *
16
- * Three things fix it, and all three are here: a border sized in proportion to the patch
17
- * ({@link decal_atlas_border}), a border that is actually **filled**, by a rule that suits what the
18
- * channel means ({@link DecalAtlasFill}), and a per-patch bound on how deep the mip chain may be
19
- * sampled ({@link decal_atlas_max_lod}), because no finite border protects every level.
20
- *
21
- * Packing, growth, repacking and uv bookkeeping are the base class's and are untouched — it already
22
- * places content at `packing + padding`, which is the whole geometry of a bordered patch.
23
- */
24
- export class DecalAtlas extends TextureAtlas {
25
- /**
26
- * @type {DecalAtlasFill}
27
- */
28
- #fill;
29
-
30
- /**
31
- * @param {DecalAtlasFill} fill
32
- * @param {number} [size] initial edge length; the atlas grows on demand
33
- */
34
- constructor(fill, size = 16) {
35
- super(size, BinaryDataType.Uint8, 4);
36
-
37
- assert.enum(fill, DecalAtlasFill, 'fill');
38
-
39
- this.#fill = fill;
40
- }
41
-
42
- /**
43
- * @returns {DecalAtlasFill}
44
- */
45
- get fill() {
46
- return this.#fill;
47
- }
48
-
49
- /**
50
- * The border is the patch's own size, not the caller's choice — every patch in one atlas has to
51
- * obey the same rule for {@link decal_atlas_max_lod}'s "+1 from the neighbour" to hold.
52
- *
53
- * @param {Sampler2D} sampler
54
- * @returns {AtlasPatch}
55
- */
56
- add(sampler) {
57
- assert.defined(sampler, 'sampler');
58
-
59
- return super.add(sampler, decal_atlas_border(sampler.width, sampler.height));
60
- }
61
-
62
- /**
63
- * @param {AtlasPatch} patch
64
- */
65
- paintPatch(patch) {
66
- const target = this.sampler;
67
- const source = patch.sampler;
68
-
69
- const width = patch.size.x;
70
- const height = patch.size.y;
71
-
72
- const x0 = patch.position.x;
73
- const y0 = patch.position.y;
74
-
75
- const border = patch.padding;
76
-
77
- const premultiply = this.#fill === DecalAtlasFill.PremultipliedCoverage;
78
-
79
- const target_data = target.data;
80
- const source_data = source.data;
81
- const target_width = target.width;
82
-
83
- for (let y = 0; y < height; y++) {
84
- const source_row = y * width * 4;
85
- const target_row = ((y0 + y) * target_width + x0) * 4;
86
-
87
- for (let x = 0; x < width; x++) {
88
- const s = source_row + x * 4;
89
- const t = target_row + x * 4;
90
-
91
- const alpha = source_data[s + 3];
92
-
93
- if (premultiply) {
94
- // integer rounding rather than truncation, so a fully opaque texel survives
95
- // the round trip exactly
96
- target_data[t] = (source_data[s] * alpha + 127) / 255 | 0;
97
- target_data[t + 1] = (source_data[s + 1] * alpha + 127) / 255 | 0;
98
- target_data[t + 2] = (source_data[s + 2] * alpha + 127) / 255 | 0;
99
- } else {
100
- target_data[t] = source_data[s];
101
- target_data[t + 1] = source_data[s + 1];
102
- target_data[t + 2] = source_data[s + 2];
103
- }
104
-
105
- target_data[t + 3] = alpha;
106
- }
107
- }
108
-
109
- if (premultiply) {
110
- this.#fill_border_zero(x0, y0, width, height, border);
111
- } else {
112
- this.#fill_border_extend(x0, y0, width, height, border);
113
- }
114
-
115
- patch.setFlag(AtlasPatchFlag.Painted);
116
- patch.last_painted_version = source.version;
117
- }
118
-
119
- /**
120
- * @param {number} x0
121
- * @param {number} y0
122
- * @param {number} width
123
- * @param {number} height
124
- * @param {number} border
125
- */
126
- #fill_border_zero(x0, y0, width, height, border) {
127
- const target = this.sampler;
128
-
129
- const data = target.data;
130
- const target_width = target.width;
131
-
132
- for (let y = y0 - border; y < y0 + height + border; y++) {
133
- const inside_rows = y >= y0 && y < y0 + height;
134
-
135
- for (let x = x0 - border; x < x0 + width + border; x++) {
136
- if (inside_rows && x >= x0 && x < x0 + width) {
137
- // the content itself, already painted
138
- x = x0 + width - 1;
139
-
140
- continue;
141
- }
142
-
143
- const t = (y * target_width + x) * 4;
144
-
145
- data[t] = 0;
146
- data[t + 1] = 0;
147
- data[t + 2] = 0;
148
- data[t + 3] = 0;
149
- }
150
- }
151
- }
152
-
153
- /**
154
- * The nearest content texel, repeated outward — corners included, which is where a fill written
155
- * as "rows then columns" leaves a hole.
156
- *
157
- * @param {number} x0
158
- * @param {number} y0
159
- * @param {number} width
160
- * @param {number} height
161
- * @param {number} border
162
- */
163
- #fill_border_extend(x0, y0, width, height, border) {
164
- const target = this.sampler;
165
-
166
- const data = target.data;
167
- const target_width = target.width;
168
-
169
- for (let y = y0 - border; y < y0 + height + border; y++) {
170
- const inside_rows = y >= y0 && y < y0 + height;
171
-
172
- // clamp to the content, on both axes independently, which is what covers the corners
173
- const source_y = y < y0 ? y0 : (y >= y0 + height ? y0 + height - 1 : y);
174
-
175
- for (let x = x0 - border; x < x0 + width + border; x++) {
176
- if (inside_rows && x >= x0 && x < x0 + width) {
177
- x = x0 + width - 1;
178
-
179
- continue;
180
- }
181
-
182
- const source_x = x < x0 ? x0 : (x >= x0 + width ? x0 + width - 1 : x);
183
-
184
- const s = (source_y * target_width + source_x) * 4;
185
- const t = (y * target_width + x) * 4;
186
-
187
- data[t] = data[s];
188
- data[t + 1] = data[s + 1];
189
- data[t + 2] = data[s + 2];
190
- data[t + 3] = data[s + 3];
191
- }
192
- }
193
- }
194
- }
1
+ import { assert } from "../../../../core/assert.js";
2
+ import { BinaryDataType } from "../../../../core/binary/type/BinaryDataType.js";
3
+ import { TextureAtlas } from "./TextureAtlas.js";
4
+ import { AtlasPatchFlag } from "./AtlasPatchFlag.js";
5
+ import { sprite_atlas_border } from "./sprite_atlas_border.js";
6
+ import { SpriteAtlasFill } from "./SpriteAtlasFill.js";
7
+
8
+ /**
9
+ * A texture atlas whose patches can be **mipmapped without bleeding into each other**.
10
+ *
11
+ * A plain {@link TextureAtlas} reserves padding around each patch but never fills it, leaving a
12
+ * zeroed gutter that every mip level past the first averages against the patch content.
13
+ *
14
+ * Three things fix it, and all three are here: a border sized in proportion to the patch
15
+ * ({@link sprite_atlas_border}), a border that is actually **filled**, by a rule that suits what the
16
+ * channel means ({@link SpriteAtlasFill}), and a per-patch bound on how deep the mip chain may be
17
+ * sampled ({@link sprite_atlas_max_lod}), because no finite border protects every level.
18
+ *
19
+ * Packing, growth, repacking and uv bookkeeping are the base class's and are untouched — it already
20
+ * places content at `packing + padding`, which is the whole geometry of a bordered patch.
21
+ */
22
+ export class SpriteAtlas extends TextureAtlas {
23
+ /**
24
+ * @type {SpriteAtlasFill}
25
+ */
26
+ #fill;
27
+
28
+ /**
29
+ * @param {SpriteAtlasFill} fill
30
+ * @param {number} [size] initial edge length; the atlas grows on demand
31
+ */
32
+ constructor(fill, size = 16) {
33
+ super(size, BinaryDataType.Uint8, 4);
34
+
35
+ assert.enum(fill, SpriteAtlasFill, 'fill');
36
+
37
+ this.#fill = fill;
38
+ }
39
+
40
+ /**
41
+ * @returns {SpriteAtlasFill}
42
+ */
43
+ get fill() {
44
+ return this.#fill;
45
+ }
46
+
47
+ /**
48
+ * The border is the patch's own size, not the caller's choice — every patch in one atlas has to
49
+ * obey the same rule for {@link sprite_atlas_max_lod}'s "+1 from the neighbour" to hold.
50
+ *
51
+ * @param {import("../sampler/Sampler2D.js").Sampler2D} sampler
52
+ * @returns {number}
53
+ */
54
+ compute_padding(sampler) {
55
+ assert.defined(sampler, 'sampler');
56
+
57
+ return sprite_atlas_border(sampler.width, sampler.height);
58
+ }
59
+
60
+ /**
61
+ * @param {import("../sampler/Sampler2D.js").Sampler2D} sampler
62
+ * @returns {import("./AtlasPatch.js").AtlasPatch}
63
+ */
64
+ add(sampler) {
65
+ assert.defined(sampler, 'sampler');
66
+
67
+ return super.add(sampler, this.compute_padding(sampler));
68
+ }
69
+
70
+ /**
71
+ * @param {import("./AtlasPatch.js").AtlasPatch} patch
72
+ */
73
+ paintPatch(patch) {
74
+ const target = this.sampler;
75
+ const source = patch.sampler;
76
+
77
+ const width = patch.size.x;
78
+ const height = patch.size.y;
79
+
80
+ const x0 = patch.position.x;
81
+ const y0 = patch.position.y;
82
+
83
+ const border = patch.padding;
84
+
85
+ const premultiply = this.#fill === SpriteAtlasFill.PremultipliedCoverage;
86
+
87
+ const target_data = target.data;
88
+ const source_data = source.data;
89
+ const target_width = target.width;
90
+
91
+ for (let y = 0; y < height; y++) {
92
+ const source_row = y * width * 4;
93
+ const target_row = ((y0 + y) * target_width + x0) * 4;
94
+
95
+ for (let x = 0; x < width; x++) {
96
+ const s = source_row + x * 4;
97
+ const t = target_row + x * 4;
98
+
99
+ const alpha = source_data[s + 3];
100
+
101
+ if (premultiply) {
102
+ // integer rounding rather than truncation, so a fully opaque texel survives
103
+ // the round trip exactly
104
+ target_data[t] = (source_data[s] * alpha + 127) / 255 | 0;
105
+ target_data[t + 1] = (source_data[s + 1] * alpha + 127) / 255 | 0;
106
+ target_data[t + 2] = (source_data[s + 2] * alpha + 127) / 255 | 0;
107
+ } else {
108
+ target_data[t] = source_data[s];
109
+ target_data[t + 1] = source_data[s + 1];
110
+ target_data[t + 2] = source_data[s + 2];
111
+ }
112
+
113
+ target_data[t + 3] = alpha;
114
+ }
115
+ }
116
+
117
+ if (premultiply) {
118
+ this.#fill_border_zero(x0, y0, width, height, border);
119
+ } else {
120
+ this.#fill_border_extend(x0, y0, width, height, border);
121
+ }
122
+
123
+ patch.setFlag(AtlasPatchFlag.Painted);
124
+ patch.last_painted_version = source.version;
125
+ }
126
+
127
+ /**
128
+ * @param {number} x0
129
+ * @param {number} y0
130
+ * @param {number} width
131
+ * @param {number} height
132
+ * @param {number} border
133
+ */
134
+ #fill_border_zero(x0, y0, width, height, border) {
135
+ const target = this.sampler;
136
+
137
+ const data = target.data;
138
+ const target_width = target.width;
139
+
140
+ for (let y = y0 - border; y < y0 + height + border; y++) {
141
+ const inside_rows = y >= y0 && y < y0 + height;
142
+
143
+ for (let x = x0 - border; x < x0 + width + border; x++) {
144
+ if (inside_rows && x >= x0 && x < x0 + width) {
145
+ // the content itself, already painted
146
+ x = x0 + width - 1;
147
+
148
+ continue;
149
+ }
150
+
151
+ const t = (y * target_width + x) * 4;
152
+
153
+ data[t] = 0;
154
+ data[t + 1] = 0;
155
+ data[t + 2] = 0;
156
+ data[t + 3] = 0;
157
+ }
158
+ }
159
+ }
160
+
161
+ /**
162
+ * The nearest content texel, repeated outward — corners included, which is where a fill written
163
+ * as "rows then columns" leaves a hole.
164
+ *
165
+ * @param {number} x0
166
+ * @param {number} y0
167
+ * @param {number} width
168
+ * @param {number} height
169
+ * @param {number} border
170
+ */
171
+ #fill_border_extend(x0, y0, width, height, border) {
172
+ const target = this.sampler;
173
+
174
+ const data = target.data;
175
+ const target_width = target.width;
176
+
177
+ for (let y = y0 - border; y < y0 + height + border; y++) {
178
+ const inside_rows = y >= y0 && y < y0 + height;
179
+
180
+ // clamp to the content, on both axes independently, which is what covers the corners
181
+ const source_y = y < y0 ? y0 : (y >= y0 + height ? y0 + height - 1 : y);
182
+
183
+ for (let x = x0 - border; x < x0 + width + border; x++) {
184
+ if (inside_rows && x >= x0 && x < x0 + width) {
185
+ x = x0 + width - 1;
186
+
187
+ continue;
188
+ }
189
+
190
+ const source_x = x < x0 ? x0 : (x >= x0 + width ? x0 + width - 1 : x);
191
+
192
+ const s = (source_y * target_width + source_x) * 4;
193
+ const t = (y * target_width + x) * 4;
194
+
195
+ data[t] = data[s];
196
+ data[t + 1] = data[s + 1];
197
+ data[t + 2] = data[s + 2];
198
+ data[t + 3] = data[s + 3];
199
+ }
200
+ }
201
+ }
202
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * How a {@link SpriteAtlas } fills the border around a patch.
3
+ *
4
+ * Two rules rather than one, because the correct fill depends on what the channel means and getting
5
+ * it wrong shows up only once the mip chain is built.
6
+ */
7
+ export type SpriteAtlasFill = number;
8
+ export namespace SpriteAtlasFill {
9
+ let PremultipliedCoverage: number;
10
+ let EdgeExtend: number;
11
+ }
12
+ //# sourceMappingURL=SpriteAtlasFill.d.ts.map