@oxy.so/bloom 7.1.1 → 7.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/assets/character-runtime/README.md +114 -19
  2. package/assets/character-runtime/authored-parts.mjs +754 -0
  3. package/assets/character-runtime/catalog-parts.mjs +362 -0
  4. package/assets/character-runtime/character-recipe.mjs +247 -0
  5. package/assets/character-runtime/clippo-geometry.mjs +679 -0
  6. package/assets/character-runtime/controller-mode.mjs +208 -0
  7. package/assets/character-runtime/cyclops-geometry.mjs +180 -0
  8. package/assets/character-runtime/legacy-engine.mjs +406 -54
  9. package/assets/character-runtime/legacy-geometry.mjs +242 -85
  10. package/assets/character-runtime/legacy-worker.mjs +82 -23
  11. package/assets/character-runtime/managed-avatar.mjs +12 -17
  12. package/assets/character-runtime/migrated-contours.mjs +2067 -0
  13. package/assets/character-runtime/migrated-faces.mjs +59 -0
  14. package/assets/character-runtime/pose-transition.mjs +523 -0
  15. package/assets/character-runtime/preparation-cache.mjs +60 -0
  16. package/assets/character-runtime/render-budget.mjs +5 -3
  17. package/assets/character-runtime/render-errors.mjs +180 -0
  18. package/assets/character-runtime/resolution.mjs +10 -0
  19. package/assets/character-runtime/runtime.mjs +744 -295
  20. package/assets/character-runtime/sha256.mjs +44 -0
  21. package/assets/character-runtime/shared-programs.mjs +534 -0
  22. package/assets/character-runtime/shared-surface.mjs +490 -0
  23. package/assets/character-runtime/shared-textures.mjs +420 -0
  24. package/assets/character-runtime/thumbnails/eyes/todd.png +0 -0
  25. package/docs/adoption-matrix.mdx +2 -2
  26. package/docs/agent-avatar.mdx +45 -8
  27. package/docs/agent-creator.mdx +13 -3
  28. package/docs/bottom-sheet.mdx +1 -1
  29. package/lib/commonjs/agent-avatar/AgentAvatar.js +1 -1
  30. package/lib/commonjs/agent-avatar/AgentAvatar.js.map +1 -1
  31. package/lib/commonjs/agent-avatar/CharacterAvatar.js +2 -1
  32. package/lib/commonjs/agent-avatar/CharacterAvatar.js.map +1 -1
  33. package/lib/commonjs/agent-avatar/character-colors.js +19 -0
  34. package/lib/commonjs/agent-avatar/character-colors.js.map +1 -0
  35. package/lib/commonjs/agent-avatar/character-shapes.js +106 -0
  36. package/lib/commonjs/agent-avatar/character-shapes.js.map +1 -0
  37. package/lib/commonjs/agent-avatar/config-character.js +4 -0
  38. package/lib/commonjs/agent-avatar/config-character.js.map +1 -1
  39. package/lib/commonjs/agent-avatar/legacy-recipe.js +19 -6
  40. package/lib/commonjs/agent-avatar/legacy-recipe.js.map +1 -1
  41. package/lib/commonjs/agent-creator/AgentCreatorBase.js +67 -107
  42. package/lib/commonjs/agent-creator/AgentCreatorBase.js.map +1 -1
  43. package/lib/commonjs/agent-creator/CharacterControls.js +23 -5
  44. package/lib/commonjs/agent-creator/CharacterControls.js.map +1 -1
  45. package/lib/commonjs/agent-creator/ClippoArtwork.js +63 -0
  46. package/lib/commonjs/agent-creator/ClippoArtwork.js.map +1 -0
  47. package/lib/commonjs/agent-creator/CyclopsArtwork.js +45 -0
  48. package/lib/commonjs/agent-creator/CyclopsArtwork.js.map +1 -0
  49. package/lib/commonjs/agent-creator/EmotionPicker.js +8 -1
  50. package/lib/commonjs/agent-creator/EmotionPicker.js.map +1 -1
  51. package/lib/commonjs/agent-creator/ShapeSilhouette.js +8 -1
  52. package/lib/commonjs/agent-creator/ShapeSilhouette.js.map +1 -1
  53. package/lib/commonjs/agent-creator/ToddArtwork.js +29 -0
  54. package/lib/commonjs/agent-creator/ToddArtwork.js.map +1 -0
  55. package/lib/commonjs/agent-creator/constants.js +16 -17
  56. package/lib/commonjs/agent-creator/constants.js.map +1 -1
  57. package/lib/commonjs/agent-creator/messages.js +1 -1
  58. package/lib/commonjs/agent-creator/messages.js.map +1 -1
  59. package/lib/commonjs/bottom-sheet/BottomSheetBase.js +33 -49
  60. package/lib/commonjs/bottom-sheet/BottomSheetBase.js.map +1 -1
  61. package/lib/commonjs/dialog/DialogBottomSheet.js +1 -1
  62. package/lib/commonjs/dialog/DialogBottomSheet.js.map +1 -1
  63. package/lib/commonjs/locale/translations/ar.js +1 -1
  64. package/lib/commonjs/locale/translations/ar.js.map +1 -1
  65. package/lib/commonjs/locale/translations/bn.js +1 -1
  66. package/lib/commonjs/locale/translations/bn.js.map +1 -1
  67. package/lib/commonjs/locale/translations/ca.js +1 -1
  68. package/lib/commonjs/locale/translations/ca.js.map +1 -1
  69. package/lib/commonjs/locale/translations/de.js +1 -1
  70. package/lib/commonjs/locale/translations/de.js.map +1 -1
  71. package/lib/commonjs/locale/translations/es.js +1 -1
  72. package/lib/commonjs/locale/translations/es.js.map +1 -1
  73. package/lib/commonjs/locale/translations/fr.js +1 -1
  74. package/lib/commonjs/locale/translations/fr.js.map +1 -1
  75. package/lib/commonjs/locale/translations/hi.js +1 -1
  76. package/lib/commonjs/locale/translations/hi.js.map +1 -1
  77. package/lib/commonjs/locale/translations/id.js +1 -1
  78. package/lib/commonjs/locale/translations/id.js.map +1 -1
  79. package/lib/commonjs/locale/translations/it.js +1 -1
  80. package/lib/commonjs/locale/translations/it.js.map +1 -1
  81. package/lib/commonjs/locale/translations/ja.js +1 -1
  82. package/lib/commonjs/locale/translations/ja.js.map +1 -1
  83. package/lib/commonjs/locale/translations/pt.js +1 -1
  84. package/lib/commonjs/locale/translations/pt.js.map +1 -1
  85. package/lib/commonjs/locale/translations/ru.js +1 -1
  86. package/lib/commonjs/locale/translations/ru.js.map +1 -1
  87. package/lib/commonjs/locale/translations/tr.js +1 -1
  88. package/lib/commonjs/locale/translations/tr.js.map +1 -1
  89. package/lib/commonjs/locale/translations/zh.js +1 -1
  90. package/lib/commonjs/locale/translations/zh.js.map +1 -1
  91. package/lib/commonjs/surface/SurfacePaint.js +17 -4
  92. package/lib/commonjs/surface/SurfacePaint.js.map +1 -1
  93. package/lib/module/agent-avatar/AgentAvatar.js +1 -1
  94. package/lib/module/agent-avatar/AgentAvatar.js.map +1 -1
  95. package/lib/module/agent-avatar/CharacterAvatar.js +2 -1
  96. package/lib/module/agent-avatar/CharacterAvatar.js.map +1 -1
  97. package/lib/module/agent-avatar/character-colors.js +15 -0
  98. package/lib/module/agent-avatar/character-colors.js.map +1 -0
  99. package/lib/module/agent-avatar/character-shapes.js +97 -0
  100. package/lib/module/agent-avatar/character-shapes.js.map +1 -0
  101. package/lib/module/agent-avatar/config-character.js +4 -0
  102. package/lib/module/agent-avatar/config-character.js.map +1 -1
  103. package/lib/module/agent-avatar/legacy-recipe.js +19 -6
  104. package/lib/module/agent-avatar/legacy-recipe.js.map +1 -1
  105. package/lib/module/agent-creator/AgentCreatorBase.js +69 -109
  106. package/lib/module/agent-creator/AgentCreatorBase.js.map +1 -1
  107. package/lib/module/agent-creator/CharacterControls.js +24 -6
  108. package/lib/module/agent-creator/CharacterControls.js.map +1 -1
  109. package/lib/module/agent-creator/ClippoArtwork.js +59 -0
  110. package/lib/module/agent-creator/ClippoArtwork.js.map +1 -0
  111. package/lib/module/agent-creator/CyclopsArtwork.js +41 -0
  112. package/lib/module/agent-creator/CyclopsArtwork.js.map +1 -0
  113. package/lib/module/agent-creator/EmotionPicker.js +8 -1
  114. package/lib/module/agent-creator/EmotionPicker.js.map +1 -1
  115. package/lib/module/agent-creator/ShapeSilhouette.js +8 -1
  116. package/lib/module/agent-creator/ShapeSilhouette.js.map +1 -1
  117. package/lib/module/agent-creator/ToddArtwork.js +25 -0
  118. package/lib/module/agent-creator/ToddArtwork.js.map +1 -0
  119. package/lib/module/agent-creator/constants.js +8 -16
  120. package/lib/module/agent-creator/constants.js.map +1 -1
  121. package/lib/module/agent-creator/messages.js +1 -1
  122. package/lib/module/agent-creator/messages.js.map +1 -1
  123. package/lib/module/bottom-sheet/BottomSheetBase.js +33 -49
  124. package/lib/module/bottom-sheet/BottomSheetBase.js.map +1 -1
  125. package/lib/module/dialog/DialogBottomSheet.js +1 -1
  126. package/lib/module/dialog/DialogBottomSheet.js.map +1 -1
  127. package/lib/module/locale/translations/ar.js +1 -1
  128. package/lib/module/locale/translations/ar.js.map +1 -1
  129. package/lib/module/locale/translations/bn.js +1 -1
  130. package/lib/module/locale/translations/bn.js.map +1 -1
  131. package/lib/module/locale/translations/ca.js +1 -1
  132. package/lib/module/locale/translations/ca.js.map +1 -1
  133. package/lib/module/locale/translations/de.js +1 -1
  134. package/lib/module/locale/translations/de.js.map +1 -1
  135. package/lib/module/locale/translations/es.js +1 -1
  136. package/lib/module/locale/translations/es.js.map +1 -1
  137. package/lib/module/locale/translations/fr.js +1 -1
  138. package/lib/module/locale/translations/fr.js.map +1 -1
  139. package/lib/module/locale/translations/hi.js +1 -1
  140. package/lib/module/locale/translations/hi.js.map +1 -1
  141. package/lib/module/locale/translations/id.js +1 -1
  142. package/lib/module/locale/translations/id.js.map +1 -1
  143. package/lib/module/locale/translations/it.js +1 -1
  144. package/lib/module/locale/translations/it.js.map +1 -1
  145. package/lib/module/locale/translations/ja.js +1 -1
  146. package/lib/module/locale/translations/ja.js.map +1 -1
  147. package/lib/module/locale/translations/pt.js +1 -1
  148. package/lib/module/locale/translations/pt.js.map +1 -1
  149. package/lib/module/locale/translations/ru.js +1 -1
  150. package/lib/module/locale/translations/ru.js.map +1 -1
  151. package/lib/module/locale/translations/tr.js +1 -1
  152. package/lib/module/locale/translations/tr.js.map +1 -1
  153. package/lib/module/locale/translations/zh.js +1 -1
  154. package/lib/module/locale/translations/zh.js.map +1 -1
  155. package/lib/module/surface/SurfacePaint.js +18 -5
  156. package/lib/module/surface/SurfacePaint.js.map +1 -1
  157. package/lib/typescript/commonjs/agent-avatar/CharacterAvatar.d.ts.map +1 -1
  158. package/lib/typescript/commonjs/agent-avatar/character-colors.d.ts +13 -0
  159. package/lib/typescript/commonjs/agent-avatar/character-colors.d.ts.map +1 -0
  160. package/lib/typescript/commonjs/agent-avatar/character-shapes.d.ts +19 -0
  161. package/lib/typescript/commonjs/agent-avatar/character-shapes.d.ts.map +1 -0
  162. package/lib/typescript/commonjs/agent-avatar/config-character.d.ts +4 -0
  163. package/lib/typescript/commonjs/agent-avatar/config-character.d.ts.map +1 -1
  164. package/lib/typescript/commonjs/agent-avatar/legacy-recipe.d.ts +2 -10
  165. package/lib/typescript/commonjs/agent-avatar/legacy-recipe.d.ts.map +1 -1
  166. package/lib/typescript/commonjs/agent-creator/AgentCreatorBase.d.ts.map +1 -1
  167. package/lib/typescript/commonjs/agent-creator/CharacterControls.d.ts +2 -1
  168. package/lib/typescript/commonjs/agent-creator/CharacterControls.d.ts.map +1 -1
  169. package/lib/typescript/commonjs/agent-creator/ClippoArtwork.d.ts +6 -0
  170. package/lib/typescript/commonjs/agent-creator/ClippoArtwork.d.ts.map +1 -0
  171. package/lib/typescript/commonjs/agent-creator/CyclopsArtwork.d.ts +5 -0
  172. package/lib/typescript/commonjs/agent-creator/CyclopsArtwork.d.ts.map +1 -0
  173. package/lib/typescript/commonjs/agent-creator/EmotionPicker.d.ts +1 -0
  174. package/lib/typescript/commonjs/agent-creator/EmotionPicker.d.ts.map +1 -1
  175. package/lib/typescript/commonjs/agent-creator/ShapeSilhouette.d.ts.map +1 -1
  176. package/lib/typescript/commonjs/agent-creator/ToddArtwork.d.ts +6 -0
  177. package/lib/typescript/commonjs/agent-creator/ToddArtwork.d.ts.map +1 -0
  178. package/lib/typescript/commonjs/agent-creator/constants.d.ts +7 -15
  179. package/lib/typescript/commonjs/agent-creator/constants.d.ts.map +1 -1
  180. package/lib/typescript/commonjs/agent-creator/messages.d.ts.map +1 -1
  181. package/lib/typescript/commonjs/bottom-sheet/BottomSheetBase.d.ts.map +1 -1
  182. package/lib/typescript/commonjs/bottom-sheet/types.d.ts +1 -0
  183. package/lib/typescript/commonjs/bottom-sheet/types.d.ts.map +1 -1
  184. package/lib/typescript/commonjs/surface/SurfacePaint.d.ts.map +1 -1
  185. package/lib/typescript/module/agent-avatar/CharacterAvatar.d.ts.map +1 -1
  186. package/lib/typescript/module/agent-avatar/character-colors.d.ts +13 -0
  187. package/lib/typescript/module/agent-avatar/character-colors.d.ts.map +1 -0
  188. package/lib/typescript/module/agent-avatar/character-shapes.d.ts +19 -0
  189. package/lib/typescript/module/agent-avatar/character-shapes.d.ts.map +1 -0
  190. package/lib/typescript/module/agent-avatar/config-character.d.ts +4 -0
  191. package/lib/typescript/module/agent-avatar/config-character.d.ts.map +1 -1
  192. package/lib/typescript/module/agent-avatar/legacy-recipe.d.ts +2 -10
  193. package/lib/typescript/module/agent-avatar/legacy-recipe.d.ts.map +1 -1
  194. package/lib/typescript/module/agent-creator/AgentCreatorBase.d.ts.map +1 -1
  195. package/lib/typescript/module/agent-creator/CharacterControls.d.ts +2 -1
  196. package/lib/typescript/module/agent-creator/CharacterControls.d.ts.map +1 -1
  197. package/lib/typescript/module/agent-creator/ClippoArtwork.d.ts +6 -0
  198. package/lib/typescript/module/agent-creator/ClippoArtwork.d.ts.map +1 -0
  199. package/lib/typescript/module/agent-creator/CyclopsArtwork.d.ts +5 -0
  200. package/lib/typescript/module/agent-creator/CyclopsArtwork.d.ts.map +1 -0
  201. package/lib/typescript/module/agent-creator/EmotionPicker.d.ts +1 -0
  202. package/lib/typescript/module/agent-creator/EmotionPicker.d.ts.map +1 -1
  203. package/lib/typescript/module/agent-creator/ShapeSilhouette.d.ts.map +1 -1
  204. package/lib/typescript/module/agent-creator/ToddArtwork.d.ts +6 -0
  205. package/lib/typescript/module/agent-creator/ToddArtwork.d.ts.map +1 -0
  206. package/lib/typescript/module/agent-creator/constants.d.ts +7 -15
  207. package/lib/typescript/module/agent-creator/constants.d.ts.map +1 -1
  208. package/lib/typescript/module/agent-creator/messages.d.ts.map +1 -1
  209. package/lib/typescript/module/bottom-sheet/BottomSheetBase.d.ts.map +1 -1
  210. package/lib/typescript/module/bottom-sheet/types.d.ts +1 -0
  211. package/lib/typescript/module/bottom-sheet/types.d.ts.map +1 -1
  212. package/lib/typescript/module/surface/SurfacePaint.d.ts.map +1 -1
  213. package/package.json +1 -1
  214. package/src/agent-avatar/AgentAvatar.tsx +1 -1
  215. package/src/agent-avatar/CharacterAvatar.tsx +4 -1
  216. package/src/agent-avatar/character-colors.ts +12 -0
  217. package/src/agent-avatar/character-shapes.ts +122 -0
  218. package/src/agent-avatar/config-character.ts +39 -6
  219. package/src/agent-avatar/legacy-recipe.ts +34 -6
  220. package/src/agent-creator/AgentCreatorBase.tsx +121 -152
  221. package/src/agent-creator/CharacterControls.tsx +39 -14
  222. package/src/agent-creator/ClippoArtwork.tsx +49 -0
  223. package/src/agent-creator/CyclopsArtwork.tsx +27 -0
  224. package/src/agent-creator/EmotionPicker.tsx +55 -16
  225. package/src/agent-creator/ShapeSilhouette.tsx +16 -1
  226. package/src/agent-creator/ToddArtwork.tsx +24 -0
  227. package/src/agent-creator/constants.ts +47 -14
  228. package/src/agent-creator/messages.ts +2 -1
  229. package/src/bottom-sheet/BottomSheetBase.tsx +24 -34
  230. package/src/bottom-sheet/types.ts +1 -0
  231. package/src/dialog/DialogBottomSheet.tsx +1 -1
  232. package/src/locale/translations/ar.ts +1 -1
  233. package/src/locale/translations/bn.ts +1 -1
  234. package/src/locale/translations/ca.ts +1 -1
  235. package/src/locale/translations/de.ts +1 -1
  236. package/src/locale/translations/es.ts +1 -1
  237. package/src/locale/translations/fr.ts +1 -1
  238. package/src/locale/translations/hi.ts +1 -1
  239. package/src/locale/translations/id.ts +1 -1
  240. package/src/locale/translations/it.ts +1 -1
  241. package/src/locale/translations/ja.ts +1 -1
  242. package/src/locale/translations/pt.ts +1 -1
  243. package/src/locale/translations/ru.ts +1 -1
  244. package/src/locale/translations/tr.ts +1 -1
  245. package/src/locale/translations/zh.ts +1 -1
  246. package/src/surface/SurfacePaint.tsx +14 -4
@@ -0,0 +1,44 @@
1
+ // SHA-256 for insecure HTTP/WebView origins without SubtleCrypto. The standard
2
+ // 32-bit round operations hash original bytes; no trusted-hash shortcut.
3
+ const K = new Uint32Array([
4
+ 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
5
+ 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
6
+ 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
7
+ 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
8
+ 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
9
+ 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
10
+ 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
11
+ 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2,
12
+ ]);
13
+ const rotate = (x,n) => (x >>> n) | (x << (32-n));
14
+ export function sha256Bytes(value) {
15
+ const source = value instanceof Uint8Array ? value : new Uint8Array(value);
16
+ const length = source.length;
17
+ const bytes = new Uint8Array(Math.ceil((length + 9)/64)*64);
18
+ bytes.set(source); bytes[length] = 128;
19
+ const view = new DataView(bytes.buffer);
20
+ view.setUint32(bytes.length-8, Math.floor(length / 0x20000000));
21
+ view.setUint32(bytes.length-4, (length*8) >>> 0);
22
+ const h = new Uint32Array([0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19]);
23
+ const w = new Uint32Array(64);
24
+ for (let offset=0;offset<bytes.length;offset+=64) {
25
+ for(let j=0;j<16;j++) w[j]=view.getUint32(offset+j*4);
26
+ for(let j=16;j<64;j++) {
27
+ const x=w[j-15], y=w[j-2];
28
+ w[j]=(w[j-16]+(rotate(x,7)^rotate(x,18)^(x>>>3))+w[j-7]+(rotate(y,17)^rotate(y,19)^(y>>>10)))>>>0;
29
+ }
30
+ let [a,b,c,d,e,f,g,z]=h;
31
+ for(let j=0;j<64;j++) {
32
+ const t1=(z+(rotate(e,6)^rotate(e,11)^rotate(e,25))+((e&f)^(~e&g))+K[j]+w[j])>>>0;
33
+ const t2=((rotate(a,2)^rotate(a,13)^rotate(a,22))+((a&b)^(a&c)^(b&c)))>>>0;
34
+ z=g;g=f;f=e;e=(d+t1)>>>0;d=c;c=b;b=a;a=(t1+t2)>>>0;
35
+ }
36
+ const next=[a,b,c,d,e,f,g,z];for(let j=0;j<8;j++)h[j]=(h[j]+next[j])>>>0;
37
+ }
38
+ return Array.from(h,word=>word.toString(16).padStart(8,'0')).join('');
39
+ }
40
+ export async function sha256(value) {
41
+ if (globalThis.crypto?.subtle)
42
+ return Array.from(new Uint8Array(await crypto.subtle.digest('SHA-256', value)),byte=>byte.toString(16).padStart(2,'0')).join('');
43
+ return sha256Bytes(value);
44
+ }
@@ -0,0 +1,534 @@
1
+ // Original shaders/programs, shared within ONE real context. The logical objects
2
+ // remain separate because Emscripten stores mutable IDs and uniform caches on them.
3
+ // This wrapper does not own the context and never suppresses context loss itself.
4
+ // Mali-G715 rejects this GLSL ES array constructor even with an explicit
5
+ // precision qualifier. Lower only the two known original-engine expressions;
6
+ // assigning the same four values separately preserves their evaluation order.
7
+ // Keep the source binaries intact and leave unrelated shaders byte-for-byte alone.
8
+ export function compatibleShaderSource(source) {
9
+ return source
10
+ .replace(
11
+ "float felipeLTC(vec3 p,mat3 transform,vec3 rect[4]) {",
12
+ "float felipeLTC(vec3 p,mat3 transform,highp vec3 rect[4]) {",
13
+ )
14
+ .replace(
15
+ "vec3 rect[4]=vec3[4](light+right-up,light-right-up,light-right+up,light+right+up);",
16
+ "highp vec3 rect[4];rect[0]=light+right-up;rect[1]=light-right-up;rect[2]=light-right+up;rect[3]=light+right+up;",
17
+ );
18
+ }
19
+
20
+ export function createSharedProgramPool(gl) {
21
+ const shaders = new WeakMap(),
22
+ programs = new WeakMap(),
23
+ locations = new WeakMap();
24
+ const shaderCache = new Map(),
25
+ programCache = new Map();
26
+ const livePrograms = new Set(),
27
+ liveShaders = new Set(),
28
+ bound = new Map();
29
+ let current = null,
30
+ disposed = false,
31
+ shaderCompiles = 0,
32
+ programLinks = 0,
33
+ uniformReplays = 0,
34
+ uniformReplaySkips = 0,
35
+ blockReplays = 0,
36
+ blockReplaySkips = 0;
37
+
38
+ const shaderKey = (s) => JSON.stringify([s.type, s.source]);
39
+ function collectShader(entry) {
40
+ if (!entry || entry.records.size || entry.programs.size) return;
41
+ gl.deleteShader(entry.real);
42
+ if (shaderCache.get(entry.key) === entry) shaderCache.delete(entry.key);
43
+ }
44
+ function releaseShader(s) {
45
+ if (!s.deleted || s.attached.size) return;
46
+ liveShaders.delete(s);
47
+ s.entry?.records.delete(s);
48
+ collectShader(s.entry);
49
+ }
50
+ function compile(s) {
51
+ const key = shaderKey(s);
52
+ if (s.entry?.key === key) return s.entry;
53
+ let entry = shaderCache.get(key);
54
+ if (!entry) {
55
+ const real = gl.createShader(s.type);
56
+ gl.shaderSource(real, compatibleShaderSource(s.source));
57
+ gl.compileShader(real);
58
+ shaderCompiles++;
59
+ entry = { key, real, records: new Set(), programs: new Set() };
60
+ shaderCache.set(key, entry);
61
+ }
62
+ const previous = s.entry;
63
+ previous?.records.delete(s);
64
+ entry.records.add(s);
65
+ s.entry = entry;
66
+ collectShader(previous);
67
+ return entry;
68
+ }
69
+ function releaseProgramEntry(p) {
70
+ const entry = p.entry;
71
+ if (!entry) return;
72
+ p.entry = null;
73
+ entry.refs.delete(p);
74
+ if (entry.owner === p) entry.owner = null;
75
+ if (entry.refs.size) return;
76
+ gl.deleteProgram(entry.real);
77
+ if (programCache.get(entry.key) === entry) programCache.delete(entry.key);
78
+ for (const shader of entry.shaders) {
79
+ shader.programs.delete(entry);
80
+ collectShader(shader);
81
+ }
82
+ }
83
+ // Active uniform reflection provides complete defaults, including uniforms an
84
+ // alias has never assigned. Otherwise switching to a new alias leaks old values.
85
+ const types = new Map([
86
+ [gl.FLOAT, ["uniform1fv", 1, Float32Array]],
87
+ [gl.FLOAT_VEC2, ["uniform2fv", 2, Float32Array]],
88
+ [gl.FLOAT_VEC3, ["uniform3fv", 3, Float32Array]],
89
+ [gl.FLOAT_VEC4, ["uniform4fv", 4, Float32Array]],
90
+ [gl.INT, ["uniform1iv", 1, Int32Array]],
91
+ [gl.INT_VEC2, ["uniform2iv", 2, Int32Array]],
92
+ [gl.INT_VEC3, ["uniform3iv", 3, Int32Array]],
93
+ [gl.INT_VEC4, ["uniform4iv", 4, Int32Array]],
94
+ [gl.UNSIGNED_INT, ["uniform1uiv", 1, Uint32Array]],
95
+ [gl.UNSIGNED_INT_VEC2, ["uniform2uiv", 2, Uint32Array]],
96
+ [gl.UNSIGNED_INT_VEC3, ["uniform3uiv", 3, Uint32Array]],
97
+ [gl.UNSIGNED_INT_VEC4, ["uniform4uiv", 4, Uint32Array]],
98
+ [gl.BOOL, ["uniform1iv", 1, Int32Array]],
99
+ [gl.BOOL_VEC2, ["uniform2iv", 2, Int32Array]],
100
+ [gl.BOOL_VEC3, ["uniform3iv", 3, Int32Array]],
101
+ [gl.BOOL_VEC4, ["uniform4iv", 4, Int32Array]],
102
+ [gl.FLOAT_MAT2, ["uniformMatrix2fv", 4, Float32Array]],
103
+ [gl.FLOAT_MAT3, ["uniformMatrix3fv", 9, Float32Array]],
104
+ [gl.FLOAT_MAT4, ["uniformMatrix4fv", 16, Float32Array]],
105
+ [gl.FLOAT_MAT2x3, ["uniformMatrix2x3fv", 6, Float32Array]],
106
+ [gl.FLOAT_MAT2x4, ["uniformMatrix2x4fv", 8, Float32Array]],
107
+ [gl.FLOAT_MAT3x2, ["uniformMatrix3x2fv", 6, Float32Array]],
108
+ [gl.FLOAT_MAT3x4, ["uniformMatrix3x4fv", 12, Float32Array]],
109
+ [gl.FLOAT_MAT4x2, ["uniformMatrix4x2fv", 8, Float32Array]],
110
+ [gl.FLOAT_MAT4x3, ["uniformMatrix4x3fv", 12, Float32Array]],
111
+ ]);
112
+ for (const name of [
113
+ "SAMPLER_2D",
114
+ "SAMPLER_CUBE",
115
+ "SAMPLER_3D",
116
+ "SAMPLER_2D_SHADOW",
117
+ "SAMPLER_2D_ARRAY",
118
+ "SAMPLER_2D_ARRAY_SHADOW",
119
+ "SAMPLER_CUBE_SHADOW",
120
+ "INT_SAMPLER_2D",
121
+ "INT_SAMPLER_3D",
122
+ "INT_SAMPLER_CUBE",
123
+ "INT_SAMPLER_2D_ARRAY",
124
+ "UNSIGNED_INT_SAMPLER_2D",
125
+ "UNSIGNED_INT_SAMPLER_3D",
126
+ "UNSIGNED_INT_SAMPLER_CUBE",
127
+ "UNSIGNED_INT_SAMPLER_2D_ARRAY",
128
+ ])
129
+ types.set(gl[name], ["uniform1iv", 1, Int32Array]);
130
+
131
+ function reflect(real) {
132
+ const uniforms = [],
133
+ names = new Map();
134
+ for (let i = 0; i < gl.getProgramParameter(real, gl.ACTIVE_UNIFORMS); i++) {
135
+ const active = gl.getActiveUniform(real, i);
136
+ const location = gl.getUniformLocation(real, active.name);
137
+ if (location === null) continue; // Uniform block members use buffers.
138
+ const type = types.get(active.type);
139
+ if (!type)
140
+ throw new Error(`Unsupported shared uniform type: ${active.type}`);
141
+ const [method, width, ArrayType] = type;
142
+ const uniform = {
143
+ name: active.name,
144
+ size: active.size,
145
+ method,
146
+ width,
147
+ ArrayType,
148
+ matrix: method.startsWith("uniformMatrix"),
149
+ location,
150
+ type: active.type,
151
+ };
152
+ const index = uniforms.push(uniform) - 1;
153
+ for (let element = 0; element < active.size; element++) {
154
+ const name = active.name.includes("[0]")
155
+ ? active.name.replace("[0]", `[${element}]`)
156
+ : active.name;
157
+ names.set(name, { index, element });
158
+ }
159
+ if (active.name.endsWith("[0]"))
160
+ names.set(active.name.slice(0, -3), { index, element: 0 });
161
+ }
162
+ return {
163
+ uniforms,
164
+ names,
165
+ blocks: gl.getProgramParameter(real, gl.ACTIVE_UNIFORM_BLOCKS),
166
+ };
167
+ }
168
+ function link(p) {
169
+ const attached = [...p.attached].map((shader) =>
170
+ compile(shaders.get(shader)),
171
+ );
172
+ const bindings = [...p.bindings].sort(([a], [b]) => a.localeCompare(b));
173
+ const key = JSON.stringify([
174
+ attached.map((s) => s.key).sort(),
175
+ bindings,
176
+ p.feedback,
177
+ ]);
178
+ let entry = programCache.get(key);
179
+ if (!entry) {
180
+ const real = p.unlinked ?? gl.createProgram();
181
+ p.unlinked = null;
182
+ for (const shader of attached) gl.attachShader(real, shader.real);
183
+ for (const [name, index] of bindings)
184
+ gl.bindAttribLocation(real, index, name);
185
+ if (p.feedback) gl.transformFeedbackVaryings(real, ...p.feedback);
186
+ gl.linkProgram(real);
187
+ programLinks++;
188
+ const linked = gl.getProgramParameter(real, gl.LINK_STATUS);
189
+ const reflection = linked
190
+ ? reflect(real)
191
+ : { uniforms: [], names: new Map(), blocks: 0 };
192
+ entry = {
193
+ key,
194
+ real,
195
+ linked,
196
+ shaders: attached,
197
+ refs: new Set(),
198
+ owner: null,
199
+ ...reflection,
200
+ };
201
+ programCache.set(key, entry);
202
+ for (const shader of attached) shader.programs.add(entry);
203
+ }
204
+ // Hold the new reference before releasing a same-key previous link.
205
+ const previous = p.entry;
206
+ if (previous !== entry) {
207
+ releaseProgramEntry(p);
208
+ entry.refs.add(p);
209
+ p.entry = entry;
210
+ }
211
+ if (p.unlinked) {
212
+ gl.deleteProgram(p.unlinked);
213
+ p.unlinked = null;
214
+ }
215
+ p.values = entry.uniforms.map((u) => new u.ArrayType(u.width * u.size));
216
+ p.blockBindings = new Uint32Array(entry.blocks);
217
+ p.locations.clear();
218
+ p.generation++;
219
+ // Relinking resets the logical program's uniforms even when its source key
220
+ // stays identical. A later useProgram must replay the reset values.
221
+ if (entry.owner === p) entry.owner = null;
222
+ if (current === p) use(p);
223
+ }
224
+ function realProgram(p) {
225
+ return p.entry?.real ?? (p.unlinked ??= gl.createProgram());
226
+ }
227
+ function equalValues(a, b) {
228
+ if (!a || a.length !== b.length) return false;
229
+ // Signed zero can be observable inside GLSL, so ordinary === is not enough.
230
+ for (let i = 0; i < b.length; i++) if (!Object.is(a[i], b[i])) return false;
231
+ return true;
232
+ }
233
+ function use(p) {
234
+ gl.useProgram(p ? realProgram(p) : null);
235
+ current = p;
236
+ if (!p?.entry || p.entry.owner === p) return;
237
+ const entry = p.entry;
238
+ const previous = entry.owner;
239
+ // The last owner records the physical program's complete uniform state,
240
+ // including partial writes. Deletion/relinking invalidates that owner, so
241
+ // unknown state still receives a complete replay, including all defaults.
242
+ for (let i = 0; i < entry.uniforms.length; i++) {
243
+ const u = entry.uniforms[i];
244
+ if (equalValues(previous?.values[i], p.values[i])) {
245
+ uniformReplaySkips++;
246
+ continue;
247
+ }
248
+ if (u.matrix) gl[u.method](u.location, false, p.values[i]);
249
+ else gl[u.method](u.location, p.values[i]);
250
+ uniformReplays++;
251
+ }
252
+ for (let i = 0; i < p.blockBindings.length; i++) {
253
+ if (previous && previous.blockBindings[i] === p.blockBindings[i]) {
254
+ blockReplaySkips++;
255
+ continue;
256
+ }
257
+ gl.uniformBlockBinding(entry.real, i, p.blockBindings[i]);
258
+ blockReplays++;
259
+ }
260
+ entry.owner = p;
261
+ }
262
+ function uniformCall(method, args) {
263
+ if (args[0] == null) return gl[method](...args);
264
+ const location = locations.get(args[0]);
265
+ if (!location) return gl[method](...args);
266
+ const { program: p, index, element, real, generation } = location;
267
+ if (current !== p || generation !== p.generation || p.deleted)
268
+ throw new Error("Shared uniform belongs to another logical program");
269
+ const result = gl[method](real, ...args.slice(1));
270
+ const u = p.entry.uniforms[index];
271
+ const vector = method.endsWith("v"),
272
+ matrix = method.startsWith("uniformMatrix");
273
+ if (matrix && args[1] !== false) return result;
274
+ let values;
275
+ if (vector) {
276
+ const at = matrix ? 2 : 1,
277
+ data = args[at];
278
+ const offset = args[at + 1] ?? 0,
279
+ length = args[at + 2] || data.length - offset;
280
+ values = Array.prototype.slice.call(data, offset, offset + length);
281
+ } else values = args.slice(1);
282
+ const offset = element * u.width;
283
+ if (
284
+ values.length % u.width === 0 &&
285
+ offset + values.length <= p.values[index].length
286
+ )
287
+ p.values[index].set(values, offset);
288
+ return result;
289
+ }
290
+ const api = {
291
+ createShader(type) {
292
+ const virtual = Object.create(WebGLShader.prototype);
293
+ const s = {
294
+ type,
295
+ source: "",
296
+ entry: null,
297
+ attached: new Set(),
298
+ deleted: false,
299
+ };
300
+ shaders.set(virtual, s);
301
+ liveShaders.add(s);
302
+ return virtual;
303
+ },
304
+ shaderSource(shader, source) {
305
+ shaders.get(shader).source = String(source);
306
+ },
307
+ compileShader(shader) {
308
+ compile(shaders.get(shader));
309
+ },
310
+ deleteShader(shader) {
311
+ if (!shader) return;
312
+ const s = shaders.get(shader);
313
+ if (!s) return gl.deleteShader(shader);
314
+ s.deleted = true;
315
+ releaseShader(s);
316
+ },
317
+ getShaderSource(shader) {
318
+ return shaders.get(shader)?.source ?? gl.getShaderSource(shader);
319
+ },
320
+ getShaderParameter(shader, parameter) {
321
+ const s = shaders.get(shader);
322
+ if (!s) return gl.getShaderParameter(shader, parameter);
323
+ if (parameter === gl.DELETE_STATUS) return s.deleted;
324
+ if (parameter === gl.SHADER_TYPE) return s.type;
325
+ return gl.getShaderParameter(compile(s).real, parameter);
326
+ },
327
+ getShaderInfoLog(shader) {
328
+ return gl.getShaderInfoLog(compile(shaders.get(shader)).real);
329
+ },
330
+ isShader(shader) {
331
+ const s = shaders.get(shader);
332
+ return s ? !s.deleted : gl.isShader(shader);
333
+ },
334
+ createProgram() {
335
+ const virtual = Object.create(WebGLProgram.prototype);
336
+ const p = {
337
+ virtual,
338
+ entry: null,
339
+ unlinked: null,
340
+ attached: new Set(),
341
+ bindings: new Map(),
342
+ feedback: null,
343
+ values: [],
344
+ blockBindings: [],
345
+ locations: new Map(),
346
+ generation: 0,
347
+ deleted: false,
348
+ };
349
+ programs.set(virtual, p);
350
+ livePrograms.add(p);
351
+ return virtual;
352
+ },
353
+ attachShader(program, shader) {
354
+ const p = programs.get(program),
355
+ s = shaders.get(shader);
356
+ p.attached.add(shader);
357
+ s.attached.add(p);
358
+ },
359
+ detachShader(program, shader) {
360
+ const p = programs.get(program),
361
+ s = shaders.get(shader);
362
+ p.attached.delete(shader);
363
+ s.attached.delete(p);
364
+ releaseShader(s);
365
+ },
366
+ getAttachedShaders(program) {
367
+ return [...programs.get(program).attached];
368
+ },
369
+ bindAttribLocation(program, index, name) {
370
+ programs.get(program).bindings.set(name, index);
371
+ },
372
+ transformFeedbackVaryings(program, varyings, mode) {
373
+ programs.get(program).feedback = [[...varyings], mode];
374
+ },
375
+ linkProgram(program) {
376
+ link(programs.get(program));
377
+ },
378
+ useProgram(program) {
379
+ use(program == null ? null : programs.get(program));
380
+ },
381
+ deleteProgram(program) {
382
+ if (!program) return;
383
+ const p = programs.get(program);
384
+ if (!p) return gl.deleteProgram(program);
385
+ if (p.deleted) return;
386
+ p.deleted = true;
387
+ if (current === p) {
388
+ gl.useProgram(null);
389
+ current = null;
390
+ }
391
+ for (const shader of p.attached) {
392
+ const s = shaders.get(shader);
393
+ s.attached.delete(p);
394
+ releaseShader(s);
395
+ }
396
+ p.attached.clear();
397
+ releaseProgramEntry(p);
398
+ if (p.unlinked) gl.deleteProgram(p.unlinked);
399
+ p.locations.clear();
400
+ p.values = [];
401
+ livePrograms.delete(p);
402
+ },
403
+ isProgram(program) {
404
+ const p = programs.get(program);
405
+ return p ? !p.deleted : gl.isProgram(program);
406
+ },
407
+ getProgramParameter(program, parameter) {
408
+ const p = programs.get(program);
409
+ if (!p) return gl.getProgramParameter(program, parameter);
410
+ if (parameter === gl.DELETE_STATUS) return p.deleted;
411
+ if (parameter === gl.ATTACHED_SHADERS) return p.attached.size;
412
+ return gl.getProgramParameter(realProgram(p), parameter);
413
+ },
414
+ getUniformLocation(program, name) {
415
+ const p = programs.get(program),
416
+ entry = p.entry;
417
+ if (p.locations.has(name)) return p.locations.get(name);
418
+ const real = gl.getUniformLocation(realProgram(p), name);
419
+ if (real === null) return null;
420
+ const slot = entry.names.get(name);
421
+ if (!slot) throw new Error(`Unknown shared uniform: ${name}`);
422
+ const virtual = Object.create(WebGLUniformLocation.prototype);
423
+ locations.set(virtual, {
424
+ program: p,
425
+ real,
426
+ ...slot,
427
+ generation: p.generation,
428
+ });
429
+ p.locations.set(name, virtual);
430
+ return virtual;
431
+ },
432
+ getUniform(program, uniform) {
433
+ const location = locations.get(uniform);
434
+ if (!location)
435
+ return gl.getUniform(realProgram(programs.get(program)), uniform);
436
+ const p = programs.get(program);
437
+ if (location.program !== p || location.generation !== p.generation)
438
+ throw new Error("Invalid shared uniform query");
439
+ const u = p.entry.uniforms[location.index];
440
+ const value = p.values[location.index].slice(
441
+ location.element * u.width,
442
+ (location.element + 1) * u.width,
443
+ );
444
+ return u.width === 1 ? value[0] : value;
445
+ },
446
+ uniformBlockBinding(program, index, binding) {
447
+ const p = programs.get(program);
448
+ p.blockBindings[index] = binding;
449
+ // This is a program operation, so it can be called while another alias is
450
+ // active. Do not overwrite that alias's live block bindings.
451
+ if (p.entry.owner === p)
452
+ gl.uniformBlockBinding(p.entry.real, index, binding);
453
+ },
454
+ getActiveUniformBlockParameter(program, index, parameter) {
455
+ const p = programs.get(program);
456
+ if (parameter === gl.UNIFORM_BLOCK_BINDING) return p.blockBindings[index];
457
+ return gl.getActiveUniformBlockParameter(
458
+ realProgram(p),
459
+ index,
460
+ parameter,
461
+ );
462
+ },
463
+ getParameter(parameter) {
464
+ if (parameter === gl.CURRENT_PROGRAM) return current?.virtual ?? null;
465
+ return gl.getParameter(parameter);
466
+ },
467
+ };
468
+ const programFirst = new Set([
469
+ "getProgramInfoLog",
470
+ "validateProgram",
471
+ "getActiveAttrib",
472
+ "getAttribLocation",
473
+ "getActiveUniform",
474
+ "getUniformIndices",
475
+ "getActiveUniforms",
476
+ "getUniformBlockIndex",
477
+ "getActiveUniformBlockName",
478
+ "getTransformFeedbackVarying",
479
+ "getFragDataLocation",
480
+ ]);
481
+ const context = new Proxy(gl, {
482
+ get(target, property) {
483
+ if (Object.hasOwn(api, property)) return api[property];
484
+ if (bound.has(property)) return bound.get(property);
485
+ const value = Reflect.get(target, property, target);
486
+ if (typeof value !== "function") return value;
487
+ if (!bound.has(property)) {
488
+ if (
489
+ /^uniform(?:[1-4](?:f|i|ui)v?|Matrix[2-4](?:x[2-4])?fv)$/.test(
490
+ String(property),
491
+ )
492
+ )
493
+ bound.set(property, (...args) => uniformCall(property, args));
494
+ else if (programFirst.has(property))
495
+ bound.set(property, (program, ...args) =>
496
+ value.call(
497
+ target,
498
+ programs.has(program)
499
+ ? realProgram(programs.get(program))
500
+ : program,
501
+ ...args,
502
+ ),
503
+ );
504
+ else bound.set(property, value.bind(target));
505
+ }
506
+ return bound.get(property);
507
+ },
508
+ });
509
+ return {
510
+ context,
511
+ stats: () => ({
512
+ logicalPrograms: livePrograms.size,
513
+ logicalShaders: liveShaders.size,
514
+ programs: programCache.size,
515
+ shaders: shaderCache.size,
516
+ programLinks,
517
+ shaderCompiles,
518
+ uniformReplays,
519
+ uniformReplaySkips,
520
+ blockReplays,
521
+ blockReplaySkips,
522
+ }),
523
+ dispose() {
524
+ if (disposed) return;
525
+ disposed = true;
526
+ for (const p of [...livePrograms]) api.deleteProgram(p.virtual);
527
+ for (const s of [...liveShaders]) {
528
+ s.deleted = true;
529
+ releaseShader(s);
530
+ }
531
+ bound.clear();
532
+ },
533
+ };
534
+ }