@woosh/meep-engine 3.61.1 → 3.61.2

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 (114) hide show
  1. package/package.json +1 -1
  2. package/src/engine/network/sim/SimActionExecutor.d.ts +4 -0
  3. package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
  4. package/src/engine/network/sim/SimActionExecutor.js +4 -0
  5. package/src/generation/foliage/material/foliage_atlas_cutout.d.ts.map +1 -1
  6. package/src/generation/foliage/material/foliage_atlas_cutout.js +21 -5
  7. package/src/generation/foliage/mesh/tree_cluster_representatives.d.ts +8 -0
  8. package/src/generation/foliage/mesh/tree_cluster_representatives.d.ts.map +1 -1
  9. package/src/generation/foliage/mesh/tree_cluster_representatives.js +178 -78
  10. package/src/generation/foliage/mesh/tree_mesh_build_bark.d.ts.map +1 -1
  11. package/src/generation/foliage/mesh/tree_mesh_build_bark.js +178 -97
  12. package/src/generation/foliage/skeleton/ShootLightField.d.ts +1 -0
  13. package/src/generation/foliage/skeleton/ShootLightField.d.ts.map +1 -1
  14. package/src/generation/foliage/skeleton/ShootLightField.js +88 -17
  15. package/src/generation/foliage/skeleton/ShootWoodHash.d.ts +5 -2
  16. package/src/generation/foliage/skeleton/ShootWoodHash.d.ts.map +1 -1
  17. package/src/generation/foliage/skeleton/ShootWoodHash.js +191 -25
  18. package/src/shade/playground/probe_clipmap/main.d.ts.map +1 -1
  19. package/src/shade/playground/probe_clipmap/main.js +4 -0
  20. package/src/shade/playground/probe_clipmap_box/README.md +55 -0
  21. package/src/shade/playground/probe_clipmap_box/index.html +185 -0
  22. package/src/shade/playground/probe_clipmap_box/main.d.ts +8 -0
  23. package/src/shade/playground/probe_clipmap_box/main.d.ts.map +1 -0
  24. package/src/shade/playground/probe_clipmap_box/main.js +323 -0
  25. package/src/shade/playground/probe_clipmap_box/scene.d.ts +93 -0
  26. package/src/shade/playground/probe_clipmap_box/scene.d.ts.map +1 -0
  27. package/src/shade/playground/probe_clipmap_box/scene.js +256 -0
  28. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  29. package/src/shade/renderer/Renderer.js +6 -1
  30. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_decode.d.ts +12 -0
  31. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_decode.d.ts.map +1 -1
  32. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_decode.js +49 -24
  33. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_encode.d.ts +12 -0
  34. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_encode.d.ts.map +1 -1
  35. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_brick4_sh3_color_encode.js +50 -19
  36. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_sh3_compress.d.ts.map +1 -1
  37. package/src/shade/renderer/global_illumination/brick4/gpu/encoding/v2/chunk_sh3_compress.js +6 -2
  38. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +5 -1
  39. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  40. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +7 -3
  41. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +6 -4
  42. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  43. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +10 -9
  44. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +12 -0
  45. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  46. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +14 -0
  47. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts +17 -22
  48. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  49. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +53 -65
  50. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.d.ts +2 -3
  51. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.d.ts.map +1 -1
  52. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.js +9 -20
  53. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts +2 -2
  54. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
  55. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +14 -19
  56. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts +1 -1
  57. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.d.ts.map +1 -1
  58. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_accumulate.js +8 -4
  59. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_admit.js +1 -1
  60. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.d.ts +2 -1
  61. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.d.ts.map +1 -1
  62. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_bounce.js +13 -18
  63. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.d.ts +1 -1
  64. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.d.ts.map +1 -1
  65. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_candidate.js +4 -2
  66. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_diffuse.d.ts.map +1 -1
  67. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_diffuse.js +4 -6
  68. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_indirect_lighting.d.ts.map +1 -1
  69. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_indirect_lighting.js +4 -7
  70. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts +4 -3
  71. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.d.ts.map +1 -1
  72. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_project.js +14 -13
  73. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts +3 -4
  74. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
  75. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +7 -15
  76. package/src/shade/renderer/light/environment/shader_downsample_environment_map.d.ts.map +1 -1
  77. package/src/shade/renderer/light/environment/shader_downsample_environment_map.js +5 -1
  78. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts +26 -8
  79. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
  80. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +170 -142
  81. package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.d.ts +1 -1
  82. package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.d.ts.map +1 -1
  83. package/src/shade/renderer/rasterize/forward/chunk_forward_sample_indirect_probe_clipmap.js +5 -8
  84. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts +15 -4
  85. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.d.ts.map +1 -1
  86. package/src/shade/renderer/shader/chunk/filter/chunk_multiscale_mean.js +33 -7
  87. package/src/shade/renderer/shader/chunk/noise/chunk_sobol_sample_vec2.d.ts +40 -0
  88. package/src/shade/renderer/shader/chunk/noise/chunk_sobol_sample_vec2.d.ts.map +1 -0
  89. package/src/shade/renderer/shader/chunk/noise/chunk_sobol_sample_vec2.js +75 -0
  90. package/src/shade/renderer/shader/chunk/noise/chunk_vdc_radical_inverse.d.ts.map +1 -1
  91. package/src/shade/renderer/shader/chunk/noise/chunk_vdc_radical_inverse.js +3 -1
  92. package/src/shade/renderer/shader/chunk/random/chunk_hash_lk.d.ts +28 -0
  93. package/src/shade/renderer/shader/chunk/random/chunk_hash_lk.d.ts.map +1 -0
  94. package/src/shade/renderer/shader/chunk/random/chunk_hash_lk.js +41 -0
  95. package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_color_add_scaled.d.ts +12 -0
  96. package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_color_add_scaled.d.ts.map +1 -0
  97. package/src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_color_add_scaled.js +24 -0
  98. package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts +3 -2
  99. package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.d.ts.map +1 -1
  100. package/src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.js +4 -0
  101. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.d.ts +2 -5
  102. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.d.ts.map +1 -1
  103. package/src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.js +3 -20
  104. package/src/shade/renderer/water/chunk_water_gi.d.ts +1 -1
  105. package/src/shade/renderer/water/chunk_water_gi.d.ts.map +1 -1
  106. package/src/shade/renderer/water/chunk_water_gi.js +6 -8
  107. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  108. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +76 -32
  109. package/src/core/math/hash/squirrel3.d.ts +0 -17
  110. package/src/core/math/hash/squirrel3.d.ts.map +0 -1
  111. package/src/core/math/hash/squirrel3.js +0 -30
  112. package/src/shade/renderer/shader/chunk/random/chunk_hash_squirrel3.d.ts +0 -12
  113. package/src/shade/renderer/shader/chunk/random/chunk_hash_squirrel3.d.ts.map +0 -1
  114. package/src/shade/renderer/shader/chunk/random/chunk_hash_squirrel3.js +0 -30
@@ -0,0 +1,75 @@
1
+ import { CodeChunk } from "../../compiler/CodeChunk.js";
2
+ import { chunk_hash_lk } from "../random/chunk_hash_lk.js";
3
+ import { chunk_hash_to_float01 } from "../random/chunk_hash_to_float01.js";
4
+
5
+
6
+ /**
7
+ * Evaluates a 2D shuffled, Owen-scrambled Sobol (0, 2)-sequence point in [0, 1)^2
8
+ * entirely in registers with zero lookup tables.
9
+ *
10
+ * Every power-of-two prefix of 2^m samples forms a fully stratified (0, m, 2)-net
11
+ * across all elementary dyadic rectangles of area 2^-m, while per-pixel seeding
12
+ * decorrelates sample sets across pixels and bounce dimensions:
13
+ *
14
+ * 1. **Index shuffling (MSB-to-LSB):** `sample_idx` is Owen-scrambled top-down via
15
+ * `reverseBits(hash_lk(reverseBits(sample_idx), ...))`. This maps every aligned
16
+ * block of 2^m contiguous indices `[k * 2^m, (k + 1) * 2^m)` bijectively onto
17
+ * another aligned 2^m block, randomizing traversal order per pixel while keeping
18
+ * bits `i_31..i_m` constant across the block so prefix stratification holds.
19
+ * 2. **Dimension 0 (Van der Corput):** Prior to radical inversion, the base-2
20
+ * Van der Corput sequence is the identity on `i`. Because bit 0 of `i` (`i_0`)
21
+ * already represents the geometric MSB (2^-1), `hash_lk` is applied directly
22
+ * followed by a single `reverseBits`.
23
+ * 3. **Dimension 1 (Sobol D1):** Computed without direction-number tables by
24
+ * multiplying `i` by the 32x32 upper-triangular Pascal matrix over GF(2)
25
+ * (`P_{k,j} = C(j, k) mod 2`, the 5-fold Kronecker power of `[1 1; 0 1]`) using
26
+ * 5 logarithmic butterfly shift-XOR stages before coordinate scrambling.
27
+ *
28
+ * For multi-bounce path tracing, pass a combined hash of `(pixel_coord, bounce_dim_pair)`
29
+ * as `pixel_seed` to construct padded 2D (0, 2)-sequences without high-dimensional
30
+ * direction tables.
31
+ *
32
+ * @see Brent Burley, "Practical Hash-based Owen Scrambling", Journal of Computer
33
+ * Graphics Techniques (JCGT), vol. 9, no. 4, pp. 1-20, 2020.
34
+ * http://jcgt.org/published/0009/04/01/
35
+ * @see Nathan Vegdahl, "Building a Better LK Hash", 2021.
36
+ * https://psychopath.io/post/2021_01_30_building_a_better_lk_hash
37
+ * @see Ilya M. Sobol', "On the distribution of points in a cube and the approximate
38
+ * evaluation of integrals", USSR Computational Mathematics and Mathematical
39
+ * Physics, vol. 7, no. 4, pp. 86-112, 1967.
40
+ *
41
+ * @type {CodeChunk}
42
+ */
43
+ export const chunk_sobol_sample_vec2 = CodeChunk.from(
44
+ //language=WGSL
45
+ `
46
+ fn sample_sobol_2d(sample_idx: u32, pixel_seed: u32) -> vec2<f32> {
47
+ // 1. Shuffle index (MSB -> LSB):
48
+ // Reverse sample_idx so s_31 is at bit 0, run LSB->MSB hash,
49
+ // then reverse back so i_0 is at bit 0 for Sobol generation.
50
+ let idx_seed = pixel_seed ^ 0x79c68e4au;
51
+ let i = reverseBits(hash_lk(reverseBits(sample_idx), idx_seed));
52
+
53
+ // 2. Dimension 0 (Van der Corput):
54
+ // i_0 (geometric MSB) is already at bit 0. Hash LSB->MSB, then
55
+ // reverse once so the geometric MSB sits at bit 31.
56
+ let u0 = reverseBits(hash_lk(i, pixel_seed ^ 0x9e3779b9u));
57
+
58
+ // 3. Dimension 1 (Sobol D1 via upper-triangular Pascal matrix):
59
+ // Requires i_0 at bit 0 so high bits (i_31..i_m, which are constant
60
+ // across 2^m-aligned blocks) shift down into low bits.
61
+ var b = i;
62
+ b ^= b >> 16u;
63
+ b ^= (b & 0xff00ff00u) >> 8u;
64
+ b ^= (b & 0xf0f0f0f0u) >> 4u;
65
+ b ^= (b & 0xccccccccu) >> 2u;
66
+ b ^= (b & 0xaaaaaaaau) >> 1u;
67
+ let u1 = reverseBits(hash_lk(b, pixel_seed ^ 0xbb67ae85u));
68
+
69
+ return vec2<f32>(hash_to_float01(u0), hash_to_float01(u1));
70
+ }
71
+ `,[
72
+ chunk_hash_lk,
73
+ chunk_hash_to_float01
74
+ ]
75
+ )
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_vdc_radical_inverse.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/shader/chunk/noise/chunk_vdc_radical_inverse.js"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wCAFU,SAAS,CAYlB;0BAlByB,6BAA6B"}
1
+ {"version":3,"file":"chunk_vdc_radical_inverse.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/shader/chunk/noise/chunk_vdc_radical_inverse.js"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,wCAFU,SAAS,CAalB;0BApByB,6BAA6B"}
@@ -1,4 +1,5 @@
1
1
  import { CodeChunk } from "../../compiler/CodeChunk.js";
2
+ import { chunk_hash_to_float01 } from "../random/chunk_hash_to_float01.js";
2
3
 
3
4
  /**
4
5
  *
@@ -12,8 +13,9 @@ export const chunk_vdc_radical_inverse = CodeChunk.from(
12
13
  fn vdc_radical_inverse(bits:u32) -> f32{
13
14
  let b = reverseBits(bits);
14
15
 
15
- return f32(b) * 2.3283064365386963e-10;
16
+ return hash_to_float01(b);
16
17
  }
17
18
  `, [
19
+ chunk_hash_to_float01
18
20
  ]
19
21
  )
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Applies Brent Burley's improved seeded Laine-Karras permutation hash for fast
3
+ * hash-based Owen scrambling of low-discrepancy sequences.
4
+ *
5
+ * Every operation in the sequence — integer addition, multiplication by an odd
6
+ * integer, and XOR-multiplication by an even constant — is a bijection modulo 2^k
7
+ * for all k in [1, 32]. Consequently, bit `i` of the output depends exclusively
8
+ * on bits `0..=i` of `x_in`, propagating entropy strictly from least-significant
9
+ * bit (LSB) to most-significant bit (MSB) while preserving prefix stratification.
10
+ *
11
+ * True Owen scrambling randomizes binary radical inverses from MSB to LSB. Unless
12
+ * your input sequence is already evaluated in bit-reversed order, wrap the call
13
+ * with `reverseBits`: `reverseBits(hash_lk(reverseBits(x), seed))`.
14
+ *
15
+ * @see Nathan Vegdahl, "Building a Better LK Hash", 2021.
16
+ * https://psychopath.io/post/2021_01_30_building_a_better_lk_hash
17
+ * @see Brent Burley, "Practical Hash-based Owen Scrambling", Journal of Computer
18
+ * Graphics Techniques (JCGT), vol. 9, no. 4, pp. 1-20, 2020.
19
+ * http://jcgt.org/published/0009/04/01/
20
+ * @see Samuli Laine and Tero Karras, "Stratified Sampling for Stochastic
21
+ * Transparency", Computer Graphics Forum (Proceedings of EGSR), vol. 30,
22
+ * no. 4, pp. 1197-1204, 2011. https://doi.org/10.1111/j.1467-8659.2011.01978.x
23
+ *
24
+ * @type {CodeChunk}
25
+ */
26
+ export const chunk_hash_lk: CodeChunk;
27
+ import { CodeChunk } from "../../compiler/CodeChunk.js";
28
+ //# sourceMappingURL=chunk_hash_lk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_hash_lk.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/shader/chunk/random/chunk_hash_lk.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,4BAFU,SAAS,CAejB;0BAxCwB,6BAA6B"}
@@ -0,0 +1,41 @@
1
+ import { CodeChunk } from "../../compiler/CodeChunk.js";
2
+
3
+ /**
4
+ * Applies Brent Burley's improved seeded Laine-Karras permutation hash for fast
5
+ * hash-based Owen scrambling of low-discrepancy sequences.
6
+ *
7
+ * Every operation in the sequence — integer addition, multiplication by an odd
8
+ * integer, and XOR-multiplication by an even constant — is a bijection modulo 2^k
9
+ * for all k in [1, 32]. Consequently, bit `i` of the output depends exclusively
10
+ * on bits `0..=i` of `x_in`, propagating entropy strictly from least-significant
11
+ * bit (LSB) to most-significant bit (MSB) while preserving prefix stratification.
12
+ *
13
+ * True Owen scrambling randomizes binary radical inverses from MSB to LSB. Unless
14
+ * your input sequence is already evaluated in bit-reversed order, wrap the call
15
+ * with `reverseBits`: `reverseBits(hash_lk(reverseBits(x), seed))`.
16
+ *
17
+ * @see Nathan Vegdahl, "Building a Better LK Hash", 2021.
18
+ * https://psychopath.io/post/2021_01_30_building_a_better_lk_hash
19
+ * @see Brent Burley, "Practical Hash-based Owen Scrambling", Journal of Computer
20
+ * Graphics Techniques (JCGT), vol. 9, no. 4, pp. 1-20, 2020.
21
+ * http://jcgt.org/published/0009/04/01/
22
+ * @see Samuli Laine and Tero Karras, "Stratified Sampling for Stochastic
23
+ * Transparency", Computer Graphics Forum (Proceedings of EGSR), vol. 30,
24
+ * no. 4, pp. 1197-1204, 2011. https://doi.org/10.1111/j.1467-8659.2011.01978.x
25
+ *
26
+ * @type {CodeChunk}
27
+ */
28
+ export const chunk_hash_lk = CodeChunk.from(
29
+ //language=WGSL
30
+ `
31
+ fn hash_lk(x_in: u32, seed: u32) -> u32 {
32
+ var x = x_in;
33
+ x ^= x * 0x3d20adeau;
34
+ x += seed;
35
+ x *= (seed >> 16u) | 1u;
36
+ x ^= x * 0x05526c56u;
37
+ x ^= x * 0x53a22864u;
38
+ return x;
39
+ }
40
+ `
41
+ );
@@ -0,0 +1,12 @@
1
+ /**
2
+ * `a + b × scale`, coefficient by coefficient: a weighted SH added to a sum.
3
+ *
4
+ * ```wgsl
5
+ * fn sh3_color_add_scaled(a: array<vec3<f32>, 9>, b: array<vec3<f32>, 9>, scale: f32) -> array<vec3<f32>, 9>
6
+ * ```
7
+ *
8
+ * @type {CodeChunk}
9
+ */
10
+ export const chunk_sh3_color_add_scaled: CodeChunk;
11
+ import { CodeChunk } from "../../compiler/CodeChunk.js";
12
+ //# sourceMappingURL=chunk_sh3_color_add_scaled.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_sh3_color_add_scaled.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/shader/chunk/spherical_harmonics/chunk_sh3_color_add_scaled.js"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,yCAFU,SAAS,CAchB;0BAvBuB,6BAA6B"}
@@ -0,0 +1,24 @@
1
+ import { CodeChunk } from "../../compiler/CodeChunk.js";
2
+
3
+ /**
4
+ * `a + b × scale`, coefficient by coefficient: a weighted SH added to a sum.
5
+ *
6
+ * ```wgsl
7
+ * fn sh3_color_add_scaled(a: array<vec3<f32>, 9>, b: array<vec3<f32>, 9>, scale: f32) -> array<vec3<f32>, 9>
8
+ * ```
9
+ *
10
+ * @type {CodeChunk}
11
+ */
12
+ export const chunk_sh3_color_add_scaled = CodeChunk.from(
13
+ //language=WGSL
14
+ `
15
+ fn sh3_color_add_scaled(a: array<vec3<f32>, 9>, b: array<vec3<f32>, 9>, scale: f32) -> array<vec3<f32>, 9> {
16
+ var out: array<vec3<f32>, 9>;
17
+
18
+ for (var i = 0; i < 9; i++) {
19
+ out[i] = a[i] + b[i] * scale;
20
+ }
21
+
22
+ return out;
23
+ }
24
+ `);
@@ -34,11 +34,11 @@ export class GPUIrradianceClipmap {
34
34
  /**
35
35
  * @returns {GPUTextureContext}
36
36
  */
37
- get texture_y(): GPUTextureContext;
37
+ get texture_y(): import("../../texture/GPUTextureContext.js").GPUTextureContext;
38
38
  /**
39
39
  * @returns {GPUTextureContext}
40
40
  */
41
- get texture_cocg(): GPUTextureContext;
41
+ get texture_cocg(): import("../../texture/GPUTextureContext.js").GPUTextureContext;
42
42
  /**
43
43
  * @returns {GPUBuffer}
44
44
  */
@@ -112,6 +112,7 @@ export class GPUIrradianceClipmap {
112
112
  destroy(): void;
113
113
  #private;
114
114
  }
115
+ export type GPUTextureContext = import("../../texture/GPUTextureContext.js").GPUTextureContext;
115
116
  import { GPUTileAtlas3D } from "../../texture/atlas/GPUTileAtlas3D.js";
116
117
  import { IrradianceCascadePlacement } from "./IrradianceCascadePlacement.js";
117
118
  import { ShaderSwitchSet } from "../../shader/compiler/ShaderSwitchSet.js";
@@ -1 +1 @@
1
- {"version":3,"file":"GPUIrradianceClipmap.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.js"],"names":[],"mappings":"AA6CA;;;;;;;;;;;;;GAaG;AACH;IA2CI;;;;;;;OAOG;IACH;QAL4B,aAAa,GAA9B,MAAM;QAC6B,UAAU,GAA7C,MAAM,GAAC,UAAU,MAAM,CAAC;QACP,SAAS,GAA1B,MAAM;QACW,WAAW,GAA5B,MAAM;OA+DhB;IAED;;OAEG;IACH,4BAEC;IAED;;OAEG;IACH,mCAEC;IAED;;OAEG;IACH,sCAEC;IAED;;OAEG;IACH,yBAEC;IAED;;OAEG;IACH,4BAEC;IAED;;;OAGG;IACH,0BAEC;IAED;;OAEG;IACH,4CAEC;IAED;;OAEG;IACH,uBAEC;IAED;;;;;;;;OAQG;IACH,oBALW,MAAM,KACN,MAAM,KACN,MAAM,oBACN,eAAe,QAgFzB;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH;QAZsG,KAAK,EAAhG,OAAO,8DAA8D,EAAE,UAAU;QACZ,MAAM,EAA3E,OAAO,kCAAkC,EAAE,gBAAgB;QACO,SAAS,EAA3E,OAAO,gCAAgC,EAAE,eAAe;QACxC,eAAe,EAA/B,MAAM;QACoB,eAAe,GAAzC,eAAe;QACuE,MAAM,GAA5F,OAAO,oDAAoD,EAAE,cAAc;QACkB,GAAG,GAAhG,OAAO,sDAAsD,EAAE,mBAAmB;QACgB,MAAM,EAAxG,OAAO,8DAA8D,EAAE,iBAAiB;QAErE,YAAY;QAC7B;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAkJtD;IAED;;OAEG;IACH,gBAQC;;CACJ;+BAxe8B,uCAAuC;2CAe3B,iCAAiC;gCApB5C,0CAA0C"}
1
+ {"version":3,"file":"GPUIrradianceClipmap.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/volumetrics/irradiance_clipmap/GPUIrradianceClipmap.js"],"names":[],"mappings":"AAiDA;;;;;;;;;;;;;GAaG;AACH;IA2CI;;;;;;;OAOG;IACH;QAL4B,aAAa,GAA9B,MAAM;QAC6B,UAAU,GAA7C,MAAM,GAAC,UAAU,MAAM,CAAC;QACP,SAAS,GAA1B,MAAM;QACW,WAAW,GAA5B,MAAM;OA+DhB;IAED;;OAEG;IACH,4BAEC;IAED;;OAEG;IACH,gFAEC;IAED;;OAEG;IACH,mFAEC;IAED;;OAEG;IACH,yBAEC;IAED;;OAEG;IACH,4BAEC;IAED;;;OAGG;IACH,0BAEC;IAED;;OAEG;IACH,4CAEC;IAED;;OAEG;IACH,uBAEC;IAED;;;;;;;;OAQG;IACH,oBALW,MAAM,KACN,MAAM,KACN,MAAM,oBACN,eAAe,QAgFzB;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH;QAZsG,KAAK,EAAhG,OAAO,8DAA8D,EAAE,UAAU;QACZ,MAAM,EAA3E,OAAO,kCAAkC,EAAE,gBAAgB;QACO,SAAS,EAA3E,OAAO,gCAAgC,EAAE,eAAe;QACxC,eAAe,EAA/B,MAAM;QACoB,eAAe,GAAzC,eAAe;QACuE,MAAM,GAA5F,OAAO,oDAAoD,EAAE,cAAc;QACkB,GAAG,GAAhG,OAAO,sDAAsD,EAAE,mBAAmB;QACgB,MAAM,EAAxG,OAAO,8DAA8D,EAAE,iBAAiB;QAErE,YAAY;QAC7B;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAkJtD;IAED;;OAEG;IACH,gBAQC;;CACJ;gCAxeY,OAAO,oCAAoC,EAAE,iBAAiB;+BAJ5C,uCAAuC;2CAmB3B,iCAAiC;gCAxB5C,0CAA0C"}
@@ -10,6 +10,10 @@ import { encoder_prepare_shader_bindings_defaults } from "../../shader/resource/
10
10
  import { SHADOWMAP_COMPARE_SAMPLER_DESCRIPTOR } from "../../shadow/map/SHADOWMAP_COMPARE_SAMPLER_DESCRIPTOR.js";
11
11
  import { GPUTileAtlas3D } from "../../texture/atlas/GPUTileAtlas3D.js";
12
12
  import { DEFAULT_RENDER_TARGET_VIEW_DESCRIPTOR } from "../../texture/DEFAULT_RENDER_TARGET_VIEW_DESCRIPTOR.js";
13
+
14
+ /**
15
+ * @typedef {import("../../texture/GPUTextureContext.js").GPUTextureContext} GPUTextureContext
16
+ */
13
17
  import {
14
18
  IRRADIANCE_CLIPMAP_CASCADE_LIMIT,
15
19
  IRRADIANCE_CLIPMAP_DEFAULT_BLEND_SKIRT,
@@ -20,11 +20,8 @@ export const chunk_irradiance_clipmap_gi_sample_lpv: CodeChunk;
20
20
  * voxel is no surface, so there is no normal to bias the point by or to weigh back faces with, nor a view.
21
21
  * Where no probe weighs anything, the environment SH, as under IBL.
22
22
  *
23
- * The probes' SH is what the volume accumulates, Metro L1 in the scale under which
24
- * `resolve_irradiance_sh_to_diffuse` gives E/π. It is handed over as the radiance SH2 that
25
- * `volumetrics_irradiance_sh_add_radiance` turns back into it: 2π × the luma, band 1 in the basis order
26
- * (y, z, x), and the chroma, which only the constant band has, over band 0's basis constant. Reads the probes'
27
- * group, `view` and `environment_sh`.
23
+ * The probes' SH is radiance SH3, as Brick4's: its bands 0 and 1 are the radiance SH2. Reads the probes' group,
24
+ * `view` and `environment_sh`.
28
25
  * @type {CodeChunk}
29
26
  */
30
27
  export const chunk_irradiance_clipmap_gi_sample_probe_clipmap: CodeChunk;
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_irradiance_clipmap_gi_sample.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.js"],"names":[],"mappings":"AAaA;;;GAGG;AACH,qDAFU,SAAS,CAcjB;AAIF;;;;GAIG;AACH,wDAFU,SAAS,CAYjB;AAEF;;;GAGG;AACH,qDAFU,SAAS,CAqBjB;AAEF;;;;;;;;;;;;GAYG;AACH,+DAFU,SAAS,CAqCjB;AAIF;;;;;GAKG;AACH,iDAFU,eAAe,CAEiE;0BA3HhE,oCAAoC;gCAC9B,0CAA0C"}
1
+ {"version":3,"file":"chunk_irradiance_clipmap_gi_sample.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/volumetrics/irradiance_clipmap/chunk_irradiance_clipmap_gi_sample.js"],"names":[],"mappings":"AAYA;;;GAGG;AACH,qDAFU,SAAS,CAcjB;AAIF;;;;GAIG;AACH,wDAFU,SAAS,CAYjB;AAEF;;;GAGG;AACH,qDAFU,SAAS,CAqBjB;AAEF;;;;;;;;;GASG;AACH,+DAFU,SAAS,CAwBjB;AAIF;;;;;GAKG;AACH,iDAFU,eAAe,CAEiE;0BA3GhE,oCAAoC;gCAC9B,0CAA0C"}
@@ -1,7 +1,6 @@
1
1
  import { chunk_brick4_sample_sh } from "../../global_illumination/brick4/gpu/draw/chunk_brick4_sample_sh.js";
2
2
  import { chunk_probe_clipmap_pick } from "../../global_illumination/probe_clipmap/probe/chunk_probe_clipmap_pick.js";
3
3
  import { INDIRECT_LIGHTING } from "../../INDIRECT_LIGHTING.js";
4
- import { chunk_YCoCg_to_rgb } from "../../shader/chunk/color/YCoCg/chunk_YCoCg_to_rgb.js";
5
4
  import { chunk_jitter_from_vectors } from "../../shader/chunk/random/chunk_jitter_from_vectors.js";
6
5
  import { ENVIRONMENT_SH_RESOURCE } from "../../light/environment/ENVIRONMENT_SH_RESOURCE.js";
7
6
  import { ShadeIndirectLightingMode } from "../../ShadeIndirectLightingMode.js";
@@ -79,11 +78,8 @@ fn irradiance_clipmap_gi_sample(position_ws: vec3<f32>) -> array<vec3<f32>, 4> {
79
78
  * voxel is no surface, so there is no normal to bias the point by or to weigh back faces with, nor a view.
80
79
  * Where no probe weighs anything, the environment SH, as under IBL.
81
80
  *
82
- * The probes' SH is what the volume accumulates, Metro L1 in the scale under which
83
- * `resolve_irradiance_sh_to_diffuse` gives E/π. It is handed over as the radiance SH2 that
84
- * `volumetrics_irradiance_sh_add_radiance` turns back into it: 2π × the luma, band 1 in the basis order
85
- * (y, z, x), and the chroma, which only the constant band has, over band 0's basis constant. Reads the probes'
86
- * group, `view` and `environment_sh`.
81
+ * The probes' SH is radiance SH3, as Brick4's: its bands 0 and 1 are the radiance SH2. Reads the probes' group,
82
+ * `view` and `environment_sh`.
87
83
  * @type {CodeChunk}
88
84
  */
89
85
  export const chunk_irradiance_clipmap_gi_sample_probe_clipmap = CodeChunk.from(
@@ -102,24 +98,11 @@ fn irradiance_clipmap_gi_sample(position_ws: vec3<f32>) -> array<vec3<f32>, 4> {
102
98
  );
103
99
  }
104
100
 
105
- // the inverse of volumetrics_irradiance_sh_add_radiance's 1 / (2 pi) and of its chroma's 1 / band 0
106
- const TWO_PI: f32 = 6.283185307179586;
107
- const BAND_0_BASIS: f32 = 0.28209479177387814;
108
-
109
- let Y = probes.sh.Y * TWO_PI;
110
-
111
- // the Metro layout is (x, y, z, constant); the basis order is (constant, y, z, x)
112
- return array<vec3<f32>, 4>(
113
- YCoCg_to_rgb(vec3<f32>(Y.w, probes.sh.CoCg * (BAND_0_BASIS * TWO_PI))),
114
- vec3<f32>(Y.y),
115
- vec3<f32>(Y.z),
116
- vec3<f32>(Y.x),
117
- );
101
+ return array<vec3<f32>, 4>(probes.sh[0], probes.sh[1], probes.sh[2], probes.sh[3]);
118
102
  }
119
103
  `, [
120
104
  chunk_probe_clipmap_pick,
121
105
  chunk_jitter_from_vectors,
122
- chunk_YCoCg_to_rgb,
123
106
  ]
124
107
  );
125
108
 
@@ -12,7 +12,7 @@ export const chunk_water_gi_ibl: CodeChunk;
12
12
  export const chunk_water_gi_brick4: CodeChunk;
13
13
  /**
14
14
  * The probe clipmap (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §9.5): each call one pick at the point, jittered by a
15
- * hash of the point and the normal, as Brick4's is. The irradiance is π × the picked SH resolved at the normal,
15
+ * hash of the point and the normal, as Brick4's is. The irradiance is the picked SH resolved at the normal,
16
16
  * the normal standing in for the view, which the irradiance call has none of. The specular is the probes'
17
17
  * radiance picked by the normal and the view (§9.3). Where no probe weighs anything, each is the environment's.
18
18
  * Reads the probes' group, `view` and `tEnvironment`.
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_water_gi.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/water/chunk_water_gi.js"],"names":[],"mappings":"AAiCA;;;;GAIG;AACH,iCAFU,SAAS,CAUoC;AAEvD;;;;GAIG;AACH,oCAFU,SAAS,CAgBwB;AAE3C;;;;;;;GAOG;AACH,2CAFU,SAAS,CAwB+E;AAElG;;;;;;GAMG;AACH,6BAFU,eAAe,CAE6C;0BA5F5C,iCAAiC;gCAC3B,uCAAuC"}
1
+ {"version":3,"file":"chunk_water_gi.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/water/chunk_water_gi.js"],"names":[],"mappings":"AAgCA;;;;GAIG;AACH,iCAFU,SAAS,CAUoC;AAEvD;;;;GAIG;AACH,oCAFU,SAAS,CAgBwB;AAE3C;;;;;;;GAOG;AACH,2CAFU,SAAS,CAuB+D;AAElF;;;;;;GAMG;AACH,6BAFU,eAAe,CAE6C;0BA3F5C,iCAAiC;gCAC3B,uCAAuC"}
@@ -9,11 +9,10 @@ import {
9
9
  } from "../global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js";
10
10
  import { INDIRECT_LIGHTING } from "../INDIRECT_LIGHTING.js";
11
11
  import { ShadeIndirectLightingMode } from "../ShadeIndirectLightingMode.js";
12
- import { PI_DECLARATION } from "../shader/chunk/math/PI_DECLARATION.js";
13
12
  import { chunk_jitter_from_vectors } from "../shader/chunk/random/chunk_jitter_from_vectors.js";
14
13
  import {
15
- chunk_resolve_irradiance_sh_to_diffuse
16
- } from "../shader/chunk/spherical_harmonics/l1i/chunk_resolve_irradiance_sh_to_diffuse.js";
14
+ chunk_sh3_color_get_irradiance_at
15
+ } from "../shader/chunk/spherical_harmonics/chunk_sh3_color_get_irradiance_at.js";
17
16
  import { CodeChunk } from "../shader/compiler/CodeChunk.js";
18
17
  import { CodeChunkChoice } from "../shader/compiler/CodeChunkChoice.js";
19
18
 
@@ -69,7 +68,7 @@ fn water_gi_specular(position: vec3<f32>, normal: vec3<f32>, view_direction: vec
69
68
 
70
69
  /**
71
70
  * The probe clipmap (PROBE_CLIPMAP_PROPOSAL_2026_10_27.md §9.5): each call one pick at the point, jittered by a
72
- * hash of the point and the normal, as Brick4's is. The irradiance is π × the picked SH resolved at the normal,
71
+ * hash of the point and the normal, as Brick4's is. The irradiance is the picked SH resolved at the normal,
73
72
  * the normal standing in for the view, which the irradiance call has none of. The specular is the probes'
74
73
  * radiance picked by the normal and the view (§9.3). Where no probe weighs anything, each is the environment's.
75
74
  * Reads the probes' group, `view` and `tEnvironment`.
@@ -80,8 +79,7 @@ fn water_gi_irradiance(position: vec3<f32>, normal: vec3<f32>) -> vec3<f32> {
80
79
  let probes = probe_clipmap_sample_sh(position, normal, normal, jitter_from_vectors(position, normal));
81
80
 
82
81
  if (probes.found) {
83
- // the resolve gives E/π
84
- return PI * resolve_irradiance_sh_to_diffuse(probes.sh.Y, probes.sh.CoCg, normal);
82
+ return sh3_color_get_irradiance_at(normal, probes.sh);
85
83
  }
86
84
 
87
85
  return get_ibl_irradiance(normal);
@@ -96,8 +94,8 @@ fn water_gi_specular(position: vec3<f32>, normal: vec3<f32>, view_direction: vec
96
94
 
97
95
  return get_ibl_radiance(view_direction, normal, roughness);
98
96
  }
99
- `, [chunk_probe_clipmap_pick, chunk_probe_clipmap_sample_radiance, chunk_resolve_irradiance_sh_to_diffuse,
100
- chunk_jitter_from_vectors, PI_DECLARATION, chunk_get_ibl_irradiance, chunk_get_ibl_radiance]);
97
+ `, [chunk_probe_clipmap_pick, chunk_probe_clipmap_sample_radiance, chunk_sh3_color_get_irradiance_at,
98
+ chunk_jitter_from_vectors, chunk_get_ibl_irradiance, chunk_get_ibl_radiance]);
101
99
 
102
100
  /**
103
101
  * The water's indirect lighting by the renderer's mode ({@link INDIRECT_LIGHTING}): IBL and LPV
@@ -1 +1 @@
1
- {"version":3,"file":"WGSLLanguageCore.d.ts","sourceRoot":"","sources":["../../../../../src/shade/wgsl/emulator/WGSLLanguageCore.js"],"names":[],"mappings":";IAs3DA;;;;;;;;;;;;;OAaG;IACH,+DAyFC"}
1
+ {"version":3,"file":"WGSLLanguageCore.d.ts","sourceRoot":"","sources":["../../../../../src/shade/wgsl/emulator/WGSLLanguageCore.js"],"names":[],"mappings":";IAk6DA;;;;;;;;;;;;;OAaG;IACH,+DAyFC"}
@@ -99,11 +99,26 @@ const BITCAST_F16 = new Float16Array(BITCAST_BUFFER);
99
99
  * @returns {*}
100
100
  */
101
101
  function makeVec(TypedArrayCtor, size, args) {
102
- if (args.length === 0) {
102
+ const n = args.length;
103
+ if (n === 0) {
103
104
  return new TypedArrayCtor(size);
104
105
  }
106
+ if (n === size && typeof args[0] === 'number') {
107
+ let all_num = true;
108
+ for (let k = 1; k < n; k++) {
109
+ if (typeof args[k] !== 'number') {
110
+ all_num = false;
111
+ break;
112
+ }
113
+ }
114
+ if (all_num) {
115
+ const out = new TypedArrayCtor(size);
116
+ for (let k = 0; k < size; k++) out[k] = args[k];
117
+ return out;
118
+ }
119
+ }
105
120
  // Single scalar → broadcast.
106
- if (args.length === 1 && typeof args[0] === 'number') {
121
+ if (n === 1 && typeof args[0] === 'number') {
107
122
  const v = args[0];
108
123
  const out = new TypedArrayCtor(size);
109
124
  for (let i = 0; i < size; i++) out[i] = v;
@@ -112,7 +127,8 @@ function makeVec(TypedArrayCtor, size, args) {
112
127
  // Otherwise flatten.
113
128
  const out = new TypedArrayCtor(size);
114
129
  let i = 0;
115
- for (const a of args) {
130
+ for (let k = 0; k < n; k++) {
131
+ const a = args[k];
116
132
  if (typeof a === 'number' || typeof a === 'boolean') {
117
133
  out[i++] = +a;
118
134
  } else if (a != null && typeof a.length === 'number') {
@@ -213,7 +229,31 @@ function is_vec(v) {
213
229
  * @param {function(number, number): number} op
214
230
  * @returns {*}
215
231
  */
232
+ const op_add = (x, y) => x + y;
233
+ const op_sub = (x, y) => x - y;
234
+ const op_mul = (x, y) => x * y;
235
+ const op_div = (x, y) => x / y;
236
+ const op_add_f32 = (x, y) => Math.fround(x + y);
237
+ const op_sub_f32 = (x, y) => Math.fround(x - y);
238
+ const op_mul_f32 = (x, y) => Math.fround(x * y);
239
+ const op_div_f32 = (x, y) => Math.fround(x / y);
240
+ const op_add_f16 = (x, y) => round_f16(x + y);
241
+ const op_sub_f16 = (x, y) => round_f16(x - y);
242
+ const op_mul_f16 = (x, y) => round_f16(x * y);
243
+ const op_div_f16 = (x, y) => round_f16(x / y);
244
+ const op_rem = (x, y) => x % y;
245
+ const op_idiv = (x, y) => Math.trunc(x / y);
246
+ const op_add_u32 = (x, y) => (x + y) >>> 0;
247
+ const op_sub_u32 = (x, y) => (x - y) >>> 0;
248
+ const op_mul_u32 = (x, y) => Math.imul(x, y) >>> 0;
249
+ const op_add_i32 = (x, y) => (x + y) | 0;
250
+ const op_sub_i32 = (x, y) => (x - y) | 0;
251
+ const op_mul_i32 = (x, y) => Math.imul(x, y) | 0;
252
+
216
253
  function binop(a, b, op) {
254
+ if (typeof a === "number" && typeof b === "number") {
255
+ return op(a, b);
256
+ }
217
257
  const a_vec = is_vec(a);
218
258
  const b_vec = is_vec(b);
219
259
 
@@ -302,7 +342,7 @@ function round_ties_to_even(x) {
302
342
  }
303
343
 
304
344
  function unop(a, op) {
305
- if (!is_vec(a)) {
345
+ if (typeof a === "number" || !is_vec(a)) {
306
346
  return op(a);
307
347
  }
308
348
  const out = new a.constructor(a.length);
@@ -321,15 +361,15 @@ function unop(a, op) {
321
361
  * @returns {*}
322
362
  */
323
363
  function ternop(a, b, c, op) {
324
- if (is_vec(a) || is_vec(b) || is_vec(c)) {
325
- const length = (is_vec(a) ? a.length : (is_vec(b) ? b.length : c.length));
326
- const ctor = (is_vec(a) ? a.constructor : (is_vec(b) ? b.constructor : c.constructor));
327
- const out = new ctor(length);
364
+ const a_vec = is_vec(a);
365
+ const b_vec = is_vec(b);
366
+ const c_vec = is_vec(c);
367
+ if (a_vec || b_vec || c_vec) {
368
+ const ref = a_vec ? a : (b_vec ? b : c);
369
+ const length = ref.length;
370
+ const out = new ref.constructor(length);
328
371
  for (let i = 0; i < length; i++) {
329
- const ai = is_vec(a) ? a[i] : a;
330
- const bi = is_vec(b) ? b[i] : b;
331
- const ci = is_vec(c) ? c[i] : c;
332
- out[i] = op(ai, bi, ci);
372
+ out[i] = op(a_vec ? a[i] : a, b_vec ? b[i] : b, c_vec ? c[i] : c);
333
373
  }
334
374
  return out;
335
375
  }
@@ -358,6 +398,10 @@ function ternop(a, b, c, op) {
358
398
  * @returns {*}
359
399
  */
360
400
  function copy_value(value) {
401
+ if (typeof value !== "object" || value === null) {
402
+ return value;
403
+ }
404
+
361
405
  if (ArrayBuffer.isView(value)) {
362
406
  return value.slice();
363
407
  }
@@ -606,10 +650,10 @@ export const WGSLLanguageCore = {
606
650
  // Arithmetic helpers (work on scalars and vectors element-wise)
607
651
  // ---------------------------------------------------------------------
608
652
 
609
- add: (a, b) => binop(a, b, (x, y) => x + y),
610
- sub: (a, b) => binop(a, b, (x, y) => x - y),
611
- mul: (a, b) => binop(a, b, (x, y) => x * y),
612
- div: (a, b) => binop(a, b, (x, y) => x / y),
653
+ add: (a, b) => typeof a === "number" && typeof b === "number" ? a + b : binop(a, b, op_add),
654
+ sub: (a, b) => typeof a === "number" && typeof b === "number" ? a - b : binop(a, b, op_sub),
655
+ mul: (a, b) => typeof a === "number" && typeof b === "number" ? a * b : binop(a, b, op_mul),
656
+ div: (a, b) => typeof a === "number" && typeof b === "number" ? a / b : binop(a, b, op_div),
613
657
 
614
658
  /*
615
659
  The same four at f32, for a SCALAR whose type the compiler knows is f32.
@@ -632,23 +676,23 @@ export const WGSLLanguageCore = {
632
676
  runtime. `Math.fround` of a vector is NaN, and binop is already idempotent here: a vec lane is
633
677
  rounded and then stored into the Float32Array that would have rounded it anyway.
634
678
  */
635
- add_f32: (a, b) => binop(a, b, (x, y) => Math.fround(x + y)),
636
- sub_f32: (a, b) => binop(a, b, (x, y) => Math.fround(x - y)),
637
- mul_f32: (a, b) => binop(a, b, (x, y) => Math.fround(x * y)),
638
- div_f32: (a, b) => binop(a, b, (x, y) => Math.fround(x / y)),
679
+ add_f32: (a, b) => typeof a === "number" && typeof b === "number" ? Math.fround(a + b) : binop(a, b, op_add_f32),
680
+ sub_f32: (a, b) => typeof a === "number" && typeof b === "number" ? Math.fround(a - b) : binop(a, b, op_sub_f32),
681
+ mul_f32: (a, b) => typeof a === "number" && typeof b === "number" ? Math.fround(a * b) : binop(a, b, op_mul_f32),
682
+ div_f32: (a, b) => typeof a === "number" && typeof b === "number" ? Math.fround(a / b) : binop(a, b, op_div_f32),
639
683
 
640
684
  // The same four at f16, for a SCALAR whose type the compiler knows is f16. Without these,
641
685
  // scalar f16 arithmetic ran in f64 (`16000.0h * 8.0h` evaluated to 128000 instead of +Infinity,
642
686
  // and `1e-3h * 1e-3h` evaluated to 1e-6 instead of underflowing in binary16).
643
- add_f16: (a, b) => binop(a, b, (x, y) => round_f16(x + y)),
644
- sub_f16: (a, b) => binop(a, b, (x, y) => round_f16(x - y)),
645
- mul_f16: (a, b) => binop(a, b, (x, y) => round_f16(x * y)),
646
- div_f16: (a, b) => binop(a, b, (x, y) => round_f16(x / y)),
647
- rem: (a, b) => binop(a, b, (x, y) => x % y),
687
+ add_f16: (a, b) => typeof a === "number" && typeof b === "number" ? round_f16(a + b) : binop(a, b, op_add_f16),
688
+ sub_f16: (a, b) => typeof a === "number" && typeof b === "number" ? round_f16(a - b) : binop(a, b, op_sub_f16),
689
+ mul_f16: (a, b) => typeof a === "number" && typeof b === "number" ? round_f16(a * b) : binop(a, b, op_mul_f16),
690
+ div_f16: (a, b) => typeof a === "number" && typeof b === "number" ? round_f16(a / b) : binop(a, b, op_div_f16),
691
+ rem: (a, b) => typeof a === "number" && typeof b === "number" ? a % b : binop(a, b, op_rem),
648
692
 
649
693
  // Integer division — truncates toward zero, matching WGSL `/` semantics on integer types.
650
694
  // The compiler routes `/` through `idiv` when both operands' tracked types are integer.
651
- idiv: (a, b) => binop(a, b, (x, y) => Math.trunc(x / y)),
695
+ idiv: (a, b) => typeof a === "number" && typeof b === "number" ? Math.trunc(a / b) : binop(a, b, op_idiv),
652
696
 
653
697
  // WGSL integer arithmetic wraps at 32 bits; JS numbers grow instead. Without wrapping, any
654
698
  // hash or PRNG that multiplies by a large odd constant leaves the u32 range within a step or
@@ -658,13 +702,13 @@ export const WGSLLanguageCore = {
658
702
  //
659
703
  // The compiler routes `+` / `-` / `*` here only when the result type is known to be an integer,
660
704
  // so float math never reaches these.
661
- add_u32: (a, b) => binop(a, b, (x, y) => (x + y) >>> 0),
662
- sub_u32: (a, b) => binop(a, b, (x, y) => (x - y) >>> 0),
663
- mul_u32: (a, b) => binop(a, b, (x, y) => Math.imul(x, y) >>> 0),
705
+ add_u32: (a, b) => typeof a === "number" && typeof b === "number" ? (a + b) >>> 0 : binop(a, b, op_add_u32),
706
+ sub_u32: (a, b) => typeof a === "number" && typeof b === "number" ? (a - b) >>> 0 : binop(a, b, op_sub_u32),
707
+ mul_u32: (a, b) => typeof a === "number" && typeof b === "number" ? Math.imul(a, b) >>> 0 : binop(a, b, op_mul_u32),
664
708
 
665
- add_i32: (a, b) => binop(a, b, (x, y) => (x + y) | 0),
666
- sub_i32: (a, b) => binop(a, b, (x, y) => (x - y) | 0),
667
- mul_i32: (a, b) => binop(a, b, (x, y) => Math.imul(x, y) | 0),
709
+ add_i32: (a, b) => typeof a === "number" && typeof b === "number" ? (a + b) | 0 : binop(a, b, op_add_i32),
710
+ sub_i32: (a, b) => typeof a === "number" && typeof b === "number" ? (a - b) | 0 : binop(a, b, op_sub_i32),
711
+ mul_i32: (a, b) => typeof a === "number" && typeof b === "number" ? Math.imul(a, b) | 0 : binop(a, b, op_mul_i32),
668
712
 
669
713
  // Element-wise bitwise / shift helpers. JS's raw `&` / `|` / `^` / `<<` / `>>` work on
670
714
  // scalars but not typed arrays (they coerce the array to a number → NaN), so the compiler
@@ -1,17 +0,0 @@
1
- /**
2
- * Based on Squirrel3 hash function by Squirrel Eiserloh
3
- *
4
- * NOTE: every step is wrapping u32 arithmetic, matching the WGSL twin `chunk_hash_squirrel3` bit
5
- * for bit. This used to multiply with plain `*`, which is a double multiply - `hash * 0x1B56C4E9`
6
- * exceeds 2^53 for any int32-sized hash, so the low bits the following `hash ^= hash >> 8` mixes
7
- * were rounded away before they were used. The result set bit 31 in exactly zero of 200,000
8
- * outputs, half the codomain unreachable, and disagreed with the GPU on every value. An in-file
9
- * comment used to blame the algorithm for the resulting low entropy; it was this port.
10
- *
11
- * @deprecated prefer {@link lowbias32}, as the WGSL chunk already says of its own twin
12
- * @see GDC 2017 presentation on "Math for Game Programmers: Noise-Based RNG"
13
- * @param {number} value expected to be an integer, if not - it will be truncated to such
14
- * @returns {number} unsigned 32-bit integer
15
- */
16
- export function squirrel3(value: number): number;
17
- //# sourceMappingURL=squirrel3.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"squirrel3.d.ts","sourceRoot":"","sources":["../../../../../src/core/math/hash/squirrel3.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AACH,iCAHW,MAAM,GACJ,MAAM,CAYlB"}