react-native-webrtc-kaleidoscope 2.0.0 → 2.1.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 (1185) hide show
  1. package/NOTICE.md +8 -8
  2. package/README.md +185 -56
  3. package/android/build.gradle +13 -0
  4. package/android/src/main/java/com/simiancraft/kaleidoscope/CompositeLayers.kt +127 -0
  5. package/android/src/main/java/com/simiancraft/kaleidoscope/EffectTuning.kt +69 -69
  6. package/android/src/main/java/com/simiancraft/kaleidoscope/KaleidoscopeModule.kt +86 -33
  7. package/android/src/main/java/com/simiancraft/kaleidoscope/Registration.kt +23 -64
  8. package/android/src/main/java/com/simiancraft/kaleidoscope/effects/CompositeFactory.kt +691 -0
  9. package/android/src/main/java/com/simiancraft/kaleidoscope/effects/LayerShaders.kt +30 -0
  10. package/android/src/main/java/com/simiancraft/kaleidoscope/effects/TransformFactory.kt +248 -200
  11. package/android/src/main/java/com/simiancraft/kaleidoscope/gpu/Egl.kt +82 -70
  12. package/android/src/main/java/com/simiancraft/kaleidoscope/gpu/Fbo.kt +50 -47
  13. package/android/src/main/java/com/simiancraft/kaleidoscope/gpu/FramePipeline.kt +106 -105
  14. package/android/src/main/java/com/simiancraft/kaleidoscope/gpu/GlDebug.kt +23 -23
  15. package/android/src/main/java/com/simiancraft/kaleidoscope/gpu/GlProgram.kt +76 -57
  16. package/android/src/main/java/com/simiancraft/kaleidoscope/gpu/Ingest.kt +92 -71
  17. package/android/src/main/java/com/simiancraft/kaleidoscope/gpu/Orientation.kt +25 -25
  18. package/android/src/main/java/com/simiancraft/kaleidoscope/gpu/Shaders.kt +57 -76
  19. package/android/src/main/java/com/simiancraft/kaleidoscope/gpu/ShadersGenerated.kt +1162 -25
  20. package/android/src/main/java/com/simiancraft/kaleidoscope/segmentation/Mask.kt +254 -242
  21. package/android/src/main/java/com/simiancraft/kaleidoscope/segmentation/MaskTuning.kt +28 -25
  22. package/android/src/main/java/com/simiancraft/kaleidoscope/segmentation/SegmentationEngine.kt +104 -98
  23. package/android/src/test/java/com/simiancraft/kaleidoscope/CompositeLayersTest.kt +165 -0
  24. package/app.plugin.js +9 -255
  25. package/catalog/composites/clouds/clouds.controls.tsx +19 -0
  26. package/catalog/composites/clouds/clouds.ts +32 -0
  27. package/catalog/composites/corporate-blobs/corporate-blobs.controls.tsx +24 -0
  28. package/catalog/composites/corporate-blobs/corporate-blobs.thumb.webp +0 -0
  29. package/catalog/composites/corporate-blobs/corporate-blobs.ts +51 -0
  30. package/catalog/composites/corporate-blobs/corporate-blobs.web.ts +42 -0
  31. package/catalog/composites/fairy-cave/fairy-cave.controls.tsx +33 -0
  32. package/catalog/composites/fairy-cave/fairy-cave.thumb.webp +0 -0
  33. package/catalog/composites/fairy-cave/fairy-cave.ts +53 -0
  34. package/catalog/composites/fairy-cave/fairy-cave.web.ts +47 -0
  35. package/catalog/composites/fairy-grotto/fairy-grotto.controls.tsx +34 -0
  36. package/catalog/composites/fairy-grotto/fairy-grotto.thumb.webp +0 -0
  37. package/catalog/composites/fairy-grotto/fairy-grotto.ts +54 -0
  38. package/catalog/composites/fairy-grotto/fairy-grotto.web.ts +47 -0
  39. package/catalog/composites/fairy-hollow/fairy-hollow.controls.tsx +34 -0
  40. package/catalog/composites/fairy-hollow/fairy-hollow.thumb.webp +0 -0
  41. package/catalog/composites/fairy-hollow/fairy-hollow.ts +55 -0
  42. package/catalog/composites/fairy-hollow/fairy-hollow.web.ts +47 -0
  43. package/catalog/composites/nebula/nebula.controls.tsx +19 -0
  44. package/catalog/composites/nebula/nebula.thumb.webp +0 -0
  45. package/catalog/composites/nebula/nebula.ts +37 -0
  46. package/catalog/composites/nebula/nebula.web.ts +30 -0
  47. package/catalog/composites/observation-deck/observation-deck.controls.tsx +28 -0
  48. package/catalog/composites/observation-deck/observation-deck.thumb.webp +0 -0
  49. package/catalog/composites/observation-deck/observation-deck.ts +59 -0
  50. package/catalog/composites/observation-deck/observation-deck.web.ts +50 -0
  51. package/catalog/composites/simianlights/simianlights.controls.tsx +19 -0
  52. package/catalog/composites/simianlights/simianlights.thumb.webp +0 -0
  53. package/catalog/composites/simianlights/simianlights.ts +34 -0
  54. package/catalog/composites/simianlights/simianlights.web.ts +29 -0
  55. package/catalog/composites/underwater/underwater.controls.tsx +19 -0
  56. package/catalog/composites/underwater/underwater.thumb.webp +0 -0
  57. package/catalog/composites/underwater/underwater.ts +42 -0
  58. package/catalog/composites/underwater/underwater.web.ts +36 -0
  59. package/catalog/composites/wizard-tower/wizard-tower.controls.tsx +23 -0
  60. package/catalog/composites/wizard-tower/wizard-tower.thumb.webp +0 -0
  61. package/catalog/composites/wizard-tower/wizard-tower.ts +44 -0
  62. package/catalog/composites/wizard-tower/wizard-tower.web.ts +35 -0
  63. package/catalog/composites/wizard-tower-night/wizard-tower-night.controls.tsx +22 -0
  64. package/catalog/composites/wizard-tower-night/wizard-tower-night.thumb.webp +0 -0
  65. package/catalog/composites/wizard-tower-night/wizard-tower-night.ts +43 -0
  66. package/catalog/composites/wizard-tower-night/wizard-tower-night.web.ts +35 -0
  67. package/catalog/images/README.md +188 -0
  68. package/catalog/images/corporate/corporate-logo.thumb.webp +0 -0
  69. package/catalog/images/corporate/corporate-logo.ts +6 -0
  70. package/catalog/images/corporate/corporate-logo.web.ts +7 -0
  71. package/catalog/images/corporate/corporate-logo.webp +0 -0
  72. package/catalog/images/debug/debug-resolutions.thumb.webp +0 -0
  73. package/catalog/images/debug/debug-resolutions.ts +6 -0
  74. package/catalog/images/debug/debug-resolutions.web.ts +7 -0
  75. package/catalog/images/fairy-caves/grotto.thumb.webp +0 -0
  76. package/catalog/images/fairy-caves/grotto.ts +6 -0
  77. package/catalog/images/fairy-caves/grotto.web.ts +7 -0
  78. package/catalog/images/fairy-caves/grotto.webp +0 -0
  79. package/catalog/images/fairy-caves/hollow.thumb.webp +0 -0
  80. package/catalog/images/fairy-caves/hollow.ts +6 -0
  81. package/catalog/images/fairy-caves/hollow.web.ts +7 -0
  82. package/catalog/images/fairy-caves/hollow.webp +0 -0
  83. package/catalog/images/fairy-caves/treehouse-2.thumb.webp +0 -0
  84. package/catalog/images/fairy-caves/treehouse-2.ts +6 -0
  85. package/catalog/images/fairy-caves/treehouse-2.web.ts +7 -0
  86. package/catalog/images/fairy-caves/treehouse-2.webp +0 -0
  87. package/catalog/images/fairy-caves/treehouse-3.thumb.webp +0 -0
  88. package/catalog/images/fairy-caves/treehouse-3.ts +6 -0
  89. package/catalog/images/fairy-caves/treehouse-3.web.ts +7 -0
  90. package/catalog/images/fairy-caves/treehouse-3.webp +0 -0
  91. package/catalog/images/fairy-caves/treehouse.thumb.webp +0 -0
  92. package/catalog/images/fairy-caves/treehouse.ts +6 -0
  93. package/catalog/images/fairy-caves/treehouse.web.ts +7 -0
  94. package/catalog/images/fairy-caves/treehouse.webp +0 -0
  95. package/catalog/images/home/home-dark.thumb.webp +0 -0
  96. package/catalog/images/home/home-dark.ts +6 -0
  97. package/catalog/images/home/home-dark.web.ts +7 -0
  98. package/catalog/images/home/home-light.thumb.webp +0 -0
  99. package/catalog/images/home/home-light.ts +6 -0
  100. package/catalog/images/home/home-light.web.ts +7 -0
  101. package/catalog/images/image-ids.ts +42 -0
  102. package/catalog/images/image.types.ts +5 -0
  103. package/catalog/images/index.ts +7 -0
  104. package/catalog/images/nature/landscape-dark.thumb.webp +0 -0
  105. package/catalog/images/nature/landscape-dark.ts +6 -0
  106. package/catalog/images/nature/landscape-dark.web.ts +7 -0
  107. package/catalog/images/nature/landscape-light.thumb.webp +0 -0
  108. package/catalog/images/nature/landscape-light.ts +6 -0
  109. package/catalog/images/nature/landscape-light.web.ts +7 -0
  110. package/catalog/images/office/office-dark.thumb.webp +0 -0
  111. package/catalog/images/office/office-dark.ts +6 -0
  112. package/catalog/images/office/office-dark.web.ts +7 -0
  113. package/catalog/images/office/office-light.thumb.webp +0 -0
  114. package/catalog/images/office/office-light.ts +6 -0
  115. package/catalog/images/office/office-light.web.ts +7 -0
  116. package/catalog/images/sci-fi/sci-fi-light.thumb.webp +0 -0
  117. package/catalog/images/sci-fi/sci-fi-light.ts +6 -0
  118. package/catalog/images/sci-fi/sci-fi-light.web.ts +7 -0
  119. package/catalog/images/simiancraft/simiancraft-dark-transparency.thumb.webp +0 -0
  120. package/catalog/images/simiancraft/simiancraft-dark-transparency.ts +6 -0
  121. package/catalog/images/simiancraft/simiancraft-dark-transparency.web.ts +9 -0
  122. package/catalog/images/simiancraft/simiancraft-dark-transparency.webp +0 -0
  123. package/catalog/images/simiancraft/simiancraft-dark.thumb.webp +0 -0
  124. package/catalog/images/simiancraft/simiancraft-dark.ts +6 -0
  125. package/catalog/images/simiancraft/simiancraft-dark.web.ts +7 -0
  126. package/catalog/images/simiancraft/simiancraft-light-transparency.thumb.webp +0 -0
  127. package/catalog/images/simiancraft/simiancraft-light-transparency.ts +6 -0
  128. package/catalog/images/simiancraft/simiancraft-light-transparency.web.ts +9 -0
  129. package/catalog/images/simiancraft/simiancraft-light-transparency.webp +0 -0
  130. package/catalog/images/simiancraft/simiancraft-light.thumb.webp +0 -0
  131. package/catalog/images/simiancraft/simiancraft-light.ts +6 -0
  132. package/catalog/images/simiancraft/simiancraft-light.web.ts +7 -0
  133. package/catalog/images/spaceship/observation-deck.thumb.webp +0 -0
  134. package/catalog/images/spaceship/observation-deck.ts +6 -0
  135. package/catalog/images/spaceship/observation-deck.web.ts +7 -0
  136. package/catalog/images/spaceship/observation-deck.webp +0 -0
  137. package/catalog/images/underwater/oceanscape-dark.thumb.webp +0 -0
  138. package/catalog/images/underwater/oceanscape-dark.ts +6 -0
  139. package/catalog/images/underwater/oceanscape-dark.web.ts +7 -0
  140. package/catalog/images/underwater/oceanscape-dark.webp +0 -0
  141. package/catalog/images/wizard-tower/wizard-tower-1.thumb.webp +0 -0
  142. package/catalog/images/wizard-tower/wizard-tower-1.ts +6 -0
  143. package/catalog/images/wizard-tower/wizard-tower-1.web.ts +7 -0
  144. package/catalog/images/wizard-tower/wizard-tower-1.webp +0 -0
  145. package/catalog/images/wizard-tower/wizard-tower-2.thumb.webp +0 -0
  146. package/catalog/images/wizard-tower/wizard-tower-2.ts +6 -0
  147. package/catalog/images/wizard-tower/wizard-tower-2.web.ts +7 -0
  148. package/catalog/images/wizard-tower/wizard-tower-2.webp +0 -0
  149. package/catalog/images/wizard-tower/wizard-tower-night.thumb.webp +0 -0
  150. package/catalog/images/wizard-tower/wizard-tower-night.ts +6 -0
  151. package/catalog/images/wizard-tower/wizard-tower-night.web.ts +7 -0
  152. package/catalog/images/wizard-tower/wizard-tower-night.webp +0 -0
  153. package/catalog/shaders/README.md +114 -0
  154. package/catalog/shaders/_shared/composite-blit.frag +26 -0
  155. package/catalog/shaders/_shared/composite-camera.frag +17 -0
  156. package/catalog/shaders/_shared/composite-image.frag +23 -0
  157. package/catalog/shaders/_shared/composite-masked.frag +26 -0
  158. package/catalog/shaders/_shared/composite-subject.frag +27 -0
  159. package/catalog/shaders/_shared/passthrough.vert +27 -0
  160. package/catalog/shaders/_shared/transform.frag +27 -0
  161. package/catalog/shaders/_shared/types.ts +63 -0
  162. package/catalog/shaders/anamorphic-lensflare/anamorphic-lensflare.form.tsx +37 -0
  163. package/catalog/shaders/anamorphic-lensflare/anamorphic-lensflare.frag +123 -0
  164. package/catalog/shaders/anamorphic-lensflare/anamorphic-lensflare.ts +106 -0
  165. package/catalog/shaders/blur/blur.form.tsx +29 -0
  166. package/catalog/shaders/blur/blur.ts +32 -0
  167. package/catalog/shaders/blur/composite-blur.frag +42 -0
  168. package/catalog/shaders/clouds/clouds.form.tsx +39 -0
  169. package/catalog/shaders/clouds/clouds.frag +128 -0
  170. package/catalog/shaders/clouds/clouds.presets.md +37 -0
  171. package/catalog/shaders/clouds/clouds.ts +124 -0
  172. package/catalog/shaders/corporate-blobs/corporate-blobs.form.tsx +44 -0
  173. package/catalog/shaders/corporate-blobs/corporate-blobs.frag +224 -0
  174. package/catalog/shaders/corporate-blobs/corporate-blobs.ts +136 -0
  175. package/catalog/shaders/fireflies/fireflies.form.tsx +33 -0
  176. package/catalog/shaders/fireflies/fireflies.frag +68 -0
  177. package/catalog/shaders/fireflies/fireflies.ts +61 -0
  178. package/catalog/shaders/godrays/godrays.form.tsx +37 -0
  179. package/catalog/shaders/godrays/godrays.frag +85 -0
  180. package/catalog/shaders/godrays/godrays.ts +105 -0
  181. package/catalog/shaders/index.ts +78 -0
  182. package/catalog/shaders/light-beams-and-motes/light-beams-and-motes.form.tsx +55 -0
  183. package/catalog/shaders/light-beams-and-motes/light-beams-and-motes.frag +262 -0
  184. package/catalog/shaders/light-beams-and-motes/light-beams-and-motes.ts +137 -0
  185. package/catalog/shaders/nebula/nebula.form.tsx +34 -0
  186. package/catalog/shaders/nebula/nebula.frag +151 -0
  187. package/catalog/shaders/nebula/nebula.ts +74 -0
  188. package/catalog/shaders/plasma/plasma.form.tsx +32 -0
  189. package/catalog/shaders/plasma/plasma.frag +55 -0
  190. package/catalog/shaders/plasma/plasma.ts +44 -0
  191. package/catalog/shaders/simianlights/simianlights.form.tsx +34 -0
  192. package/catalog/shaders/simianlights/simianlights.frag +151 -0
  193. package/catalog/shaders/simianlights/simianlights.ts +73 -0
  194. package/dist/catalog/composites/clouds/clouds.controls.d.ts +3 -0
  195. package/dist/catalog/composites/clouds/clouds.controls.d.ts.map +1 -0
  196. package/dist/catalog/composites/clouds/clouds.controls.js +11 -0
  197. package/dist/catalog/composites/clouds/clouds.controls.js.map +1 -0
  198. package/dist/catalog/composites/clouds/clouds.d.ts +26 -0
  199. package/dist/catalog/composites/clouds/clouds.d.ts.map +1 -0
  200. package/dist/catalog/composites/clouds/clouds.js +33 -0
  201. package/dist/catalog/composites/clouds/clouds.js.map +1 -0
  202. package/dist/catalog/composites/corporate-blobs/corporate-blobs.controls.d.ts +3 -0
  203. package/dist/catalog/composites/corporate-blobs/corporate-blobs.controls.d.ts.map +1 -0
  204. package/dist/catalog/composites/corporate-blobs/corporate-blobs.controls.js +13 -0
  205. package/dist/catalog/composites/corporate-blobs/corporate-blobs.controls.js.map +1 -0
  206. package/dist/catalog/composites/corporate-blobs/corporate-blobs.d.ts +37 -0
  207. package/dist/catalog/composites/corporate-blobs/corporate-blobs.d.ts.map +1 -0
  208. package/dist/catalog/composites/corporate-blobs/corporate-blobs.js +52 -0
  209. package/dist/catalog/composites/corporate-blobs/corporate-blobs.js.map +1 -0
  210. package/dist/catalog/composites/corporate-blobs/corporate-blobs.thumb.webp +0 -0
  211. package/dist/catalog/composites/corporate-blobs/corporate-blobs.web.d.ts +37 -0
  212. package/dist/catalog/composites/corporate-blobs/corporate-blobs.web.d.ts.map +1 -0
  213. package/dist/catalog/composites/corporate-blobs/corporate-blobs.web.js +46 -0
  214. package/dist/catalog/composites/corporate-blobs/corporate-blobs.web.js.map +1 -0
  215. package/dist/catalog/composites/fairy-cave/fairy-cave.controls.d.ts +3 -0
  216. package/dist/catalog/composites/fairy-cave/fairy-cave.controls.d.ts.map +1 -0
  217. package/dist/catalog/composites/fairy-cave/fairy-cave.controls.js +13 -0
  218. package/dist/catalog/composites/fairy-cave/fairy-cave.controls.js.map +1 -0
  219. package/dist/catalog/composites/fairy-cave/fairy-cave.d.ts +42 -0
  220. package/dist/catalog/composites/fairy-cave/fairy-cave.d.ts.map +1 -0
  221. package/dist/catalog/composites/fairy-cave/fairy-cave.js +54 -0
  222. package/dist/catalog/composites/fairy-cave/fairy-cave.js.map +1 -0
  223. package/dist/catalog/composites/fairy-cave/fairy-cave.thumb.webp +0 -0
  224. package/dist/catalog/composites/fairy-cave/fairy-cave.web.d.ts +42 -0
  225. package/dist/catalog/composites/fairy-cave/fairy-cave.web.d.ts.map +1 -0
  226. package/dist/catalog/composites/fairy-cave/fairy-cave.web.js +51 -0
  227. package/dist/catalog/composites/fairy-cave/fairy-cave.web.js.map +1 -0
  228. package/dist/catalog/composites/fairy-grotto/fairy-grotto.controls.d.ts +3 -0
  229. package/dist/catalog/composites/fairy-grotto/fairy-grotto.controls.d.ts.map +1 -0
  230. package/dist/catalog/composites/fairy-grotto/fairy-grotto.controls.js +14 -0
  231. package/dist/catalog/composites/fairy-grotto/fairy-grotto.controls.js.map +1 -0
  232. package/dist/catalog/composites/fairy-grotto/fairy-grotto.d.ts +42 -0
  233. package/dist/catalog/composites/fairy-grotto/fairy-grotto.d.ts.map +1 -0
  234. package/dist/catalog/composites/fairy-grotto/fairy-grotto.js +55 -0
  235. package/dist/catalog/composites/fairy-grotto/fairy-grotto.js.map +1 -0
  236. package/dist/catalog/composites/fairy-grotto/fairy-grotto.thumb.webp +0 -0
  237. package/dist/catalog/composites/fairy-grotto/fairy-grotto.web.d.ts +42 -0
  238. package/dist/catalog/composites/fairy-grotto/fairy-grotto.web.d.ts.map +1 -0
  239. package/dist/catalog/composites/fairy-grotto/fairy-grotto.web.js +51 -0
  240. package/dist/catalog/composites/fairy-grotto/fairy-grotto.web.js.map +1 -0
  241. package/dist/catalog/composites/fairy-hollow/fairy-hollow.controls.d.ts +3 -0
  242. package/dist/catalog/composites/fairy-hollow/fairy-hollow.controls.d.ts.map +1 -0
  243. package/dist/catalog/composites/fairy-hollow/fairy-hollow.controls.js +14 -0
  244. package/dist/catalog/composites/fairy-hollow/fairy-hollow.controls.js.map +1 -0
  245. package/dist/catalog/composites/fairy-hollow/fairy-hollow.d.ts +42 -0
  246. package/dist/catalog/composites/fairy-hollow/fairy-hollow.d.ts.map +1 -0
  247. package/dist/catalog/composites/fairy-hollow/fairy-hollow.js +56 -0
  248. package/dist/catalog/composites/fairy-hollow/fairy-hollow.js.map +1 -0
  249. package/dist/catalog/composites/fairy-hollow/fairy-hollow.thumb.webp +0 -0
  250. package/dist/catalog/composites/fairy-hollow/fairy-hollow.web.d.ts +42 -0
  251. package/dist/catalog/composites/fairy-hollow/fairy-hollow.web.d.ts.map +1 -0
  252. package/dist/catalog/composites/fairy-hollow/fairy-hollow.web.js +51 -0
  253. package/dist/catalog/composites/fairy-hollow/fairy-hollow.web.js.map +1 -0
  254. package/dist/catalog/composites/nebula/nebula.controls.d.ts +3 -0
  255. package/dist/catalog/composites/nebula/nebula.controls.d.ts.map +1 -0
  256. package/dist/catalog/composites/nebula/nebula.controls.js +11 -0
  257. package/dist/catalog/composites/nebula/nebula.controls.js.map +1 -0
  258. package/dist/catalog/composites/nebula/nebula.d.ts +22 -0
  259. package/dist/catalog/composites/nebula/nebula.d.ts.map +1 -0
  260. package/dist/catalog/composites/nebula/nebula.js +38 -0
  261. package/dist/catalog/composites/nebula/nebula.js.map +1 -0
  262. package/dist/catalog/composites/nebula/nebula.thumb.webp +0 -0
  263. package/dist/catalog/composites/nebula/nebula.web.d.ts +22 -0
  264. package/dist/catalog/composites/nebula/nebula.web.d.ts.map +1 -0
  265. package/dist/catalog/composites/nebula/nebula.web.js +34 -0
  266. package/dist/catalog/composites/nebula/nebula.web.js.map +1 -0
  267. package/dist/catalog/composites/observation-deck/observation-deck.controls.d.ts +3 -0
  268. package/dist/catalog/composites/observation-deck/observation-deck.controls.d.ts.map +1 -0
  269. package/dist/catalog/composites/observation-deck/observation-deck.controls.js +13 -0
  270. package/dist/catalog/composites/observation-deck/observation-deck.controls.js.map +1 -0
  271. package/dist/catalog/composites/observation-deck/observation-deck.d.ts +41 -0
  272. package/dist/catalog/composites/observation-deck/observation-deck.d.ts.map +1 -0
  273. package/dist/catalog/composites/observation-deck/observation-deck.js +60 -0
  274. package/dist/catalog/composites/observation-deck/observation-deck.js.map +1 -0
  275. package/dist/catalog/composites/observation-deck/observation-deck.thumb.webp +0 -0
  276. package/dist/catalog/composites/observation-deck/observation-deck.web.d.ts +41 -0
  277. package/dist/catalog/composites/observation-deck/observation-deck.web.d.ts.map +1 -0
  278. package/dist/catalog/composites/observation-deck/observation-deck.web.js +54 -0
  279. package/dist/catalog/composites/observation-deck/observation-deck.web.js.map +1 -0
  280. package/dist/catalog/composites/simianlights/simianlights.controls.d.ts +3 -0
  281. package/dist/catalog/composites/simianlights/simianlights.controls.d.ts.map +1 -0
  282. package/dist/catalog/composites/simianlights/simianlights.controls.js +11 -0
  283. package/dist/catalog/composites/simianlights/simianlights.controls.js.map +1 -0
  284. package/dist/catalog/composites/simianlights/simianlights.d.ts +22 -0
  285. package/dist/catalog/composites/simianlights/simianlights.d.ts.map +1 -0
  286. package/dist/catalog/composites/simianlights/simianlights.js +30 -0
  287. package/dist/catalog/composites/simianlights/simianlights.js.map +1 -0
  288. package/dist/catalog/composites/simianlights/simianlights.thumb.webp +0 -0
  289. package/dist/catalog/composites/simianlights/simianlights.web.d.ts +22 -0
  290. package/dist/catalog/composites/simianlights/simianlights.web.d.ts.map +1 -0
  291. package/dist/catalog/composites/simianlights/simianlights.web.js +33 -0
  292. package/dist/catalog/composites/simianlights/simianlights.web.js.map +1 -0
  293. package/dist/catalog/composites/underwater/underwater.controls.d.ts +3 -0
  294. package/dist/catalog/composites/underwater/underwater.controls.d.ts.map +1 -0
  295. package/dist/catalog/composites/underwater/underwater.controls.js +11 -0
  296. package/dist/catalog/composites/underwater/underwater.controls.js.map +1 -0
  297. package/dist/catalog/composites/underwater/underwater.d.ts +30 -0
  298. package/dist/catalog/composites/underwater/underwater.d.ts.map +1 -0
  299. package/dist/catalog/composites/underwater/underwater.js +43 -0
  300. package/dist/catalog/composites/underwater/underwater.js.map +1 -0
  301. package/dist/catalog/composites/underwater/underwater.thumb.webp +0 -0
  302. package/dist/catalog/composites/underwater/underwater.web.d.ts +30 -0
  303. package/dist/catalog/composites/underwater/underwater.web.d.ts.map +1 -0
  304. package/dist/catalog/composites/underwater/underwater.web.js +40 -0
  305. package/dist/catalog/composites/underwater/underwater.web.js.map +1 -0
  306. package/dist/catalog/composites/wizard-tower/wizard-tower.controls.d.ts +3 -0
  307. package/dist/catalog/composites/wizard-tower/wizard-tower.controls.d.ts.map +1 -0
  308. package/dist/catalog/composites/wizard-tower/wizard-tower.controls.js +15 -0
  309. package/dist/catalog/composites/wizard-tower/wizard-tower.controls.js.map +1 -0
  310. package/dist/catalog/composites/wizard-tower/wizard-tower.d.ts +31 -0
  311. package/dist/catalog/composites/wizard-tower/wizard-tower.d.ts.map +1 -0
  312. package/dist/catalog/composites/wizard-tower/wizard-tower.js +45 -0
  313. package/dist/catalog/composites/wizard-tower/wizard-tower.js.map +1 -0
  314. package/dist/catalog/composites/wizard-tower/wizard-tower.thumb.webp +0 -0
  315. package/dist/catalog/composites/wizard-tower/wizard-tower.web.d.ts +31 -0
  316. package/dist/catalog/composites/wizard-tower/wizard-tower.web.d.ts.map +1 -0
  317. package/dist/catalog/composites/wizard-tower/wizard-tower.web.js +39 -0
  318. package/dist/catalog/composites/wizard-tower/wizard-tower.web.js.map +1 -0
  319. package/dist/catalog/composites/wizard-tower-night/wizard-tower-night.controls.d.ts +3 -0
  320. package/dist/catalog/composites/wizard-tower-night/wizard-tower-night.controls.d.ts.map +1 -0
  321. package/dist/catalog/composites/wizard-tower-night/wizard-tower-night.controls.js +14 -0
  322. package/dist/catalog/composites/wizard-tower-night/wizard-tower-night.controls.js.map +1 -0
  323. package/dist/catalog/composites/wizard-tower-night/wizard-tower-night.d.ts +31 -0
  324. package/dist/catalog/composites/wizard-tower-night/wizard-tower-night.d.ts.map +1 -0
  325. package/dist/catalog/composites/wizard-tower-night/wizard-tower-night.js +44 -0
  326. package/dist/catalog/composites/wizard-tower-night/wizard-tower-night.js.map +1 -0
  327. package/dist/catalog/composites/wizard-tower-night/wizard-tower-night.thumb.webp +0 -0
  328. package/dist/catalog/composites/wizard-tower-night/wizard-tower-night.web.d.ts +31 -0
  329. package/dist/catalog/composites/wizard-tower-night/wizard-tower-night.web.d.ts.map +1 -0
  330. package/dist/catalog/composites/wizard-tower-night/wizard-tower-night.web.js +39 -0
  331. package/dist/catalog/composites/wizard-tower-night/wizard-tower-night.web.js.map +1 -0
  332. package/dist/catalog/images/corporate/corporate-logo.d.ts +3 -0
  333. package/dist/catalog/images/corporate/corporate-logo.d.ts.map +1 -0
  334. package/dist/catalog/images/corporate/corporate-logo.js +8 -0
  335. package/dist/catalog/images/corporate/corporate-logo.js.map +1 -0
  336. package/dist/catalog/images/corporate/corporate-logo.thumb.webp +0 -0
  337. package/dist/catalog/images/corporate/corporate-logo.web.d.ts +3 -0
  338. package/dist/catalog/images/corporate/corporate-logo.web.d.ts.map +1 -0
  339. package/dist/catalog/images/corporate/corporate-logo.web.js +12 -0
  340. package/dist/catalog/images/corporate/corporate-logo.web.js.map +1 -0
  341. package/dist/catalog/images/corporate/corporate-logo.webp +0 -0
  342. package/dist/catalog/images/debug/debug-resolutions.d.ts +3 -0
  343. package/dist/catalog/images/debug/debug-resolutions.d.ts.map +1 -0
  344. package/dist/catalog/images/debug/debug-resolutions.js +8 -0
  345. package/dist/catalog/images/debug/debug-resolutions.js.map +1 -0
  346. package/dist/catalog/images/debug/debug-resolutions.thumb.webp +0 -0
  347. package/dist/catalog/images/debug/debug-resolutions.web.d.ts +3 -0
  348. package/dist/catalog/images/debug/debug-resolutions.web.d.ts.map +1 -0
  349. package/dist/catalog/images/debug/debug-resolutions.web.js +12 -0
  350. package/dist/catalog/images/debug/debug-resolutions.web.js.map +1 -0
  351. package/dist/catalog/images/fairy-caves/grotto.d.ts +3 -0
  352. package/dist/catalog/images/fairy-caves/grotto.d.ts.map +1 -0
  353. package/dist/catalog/images/fairy-caves/grotto.js +8 -0
  354. package/dist/catalog/images/fairy-caves/grotto.js.map +1 -0
  355. package/dist/catalog/images/fairy-caves/grotto.thumb.webp +0 -0
  356. package/dist/catalog/images/fairy-caves/grotto.web.d.ts +3 -0
  357. package/dist/catalog/images/fairy-caves/grotto.web.d.ts.map +1 -0
  358. package/dist/catalog/images/fairy-caves/grotto.web.js +12 -0
  359. package/dist/catalog/images/fairy-caves/grotto.web.js.map +1 -0
  360. package/dist/catalog/images/fairy-caves/grotto.webp +0 -0
  361. package/dist/catalog/images/fairy-caves/hollow.d.ts +3 -0
  362. package/dist/catalog/images/fairy-caves/hollow.d.ts.map +1 -0
  363. package/dist/catalog/images/fairy-caves/hollow.js +8 -0
  364. package/dist/catalog/images/fairy-caves/hollow.js.map +1 -0
  365. package/dist/catalog/images/fairy-caves/hollow.thumb.webp +0 -0
  366. package/dist/catalog/images/fairy-caves/hollow.web.d.ts +3 -0
  367. package/dist/catalog/images/fairy-caves/hollow.web.d.ts.map +1 -0
  368. package/dist/catalog/images/fairy-caves/hollow.web.js +12 -0
  369. package/dist/catalog/images/fairy-caves/hollow.web.js.map +1 -0
  370. package/dist/catalog/images/fairy-caves/hollow.webp +0 -0
  371. package/dist/catalog/images/fairy-caves/treehouse-2.d.ts +3 -0
  372. package/dist/catalog/images/fairy-caves/treehouse-2.d.ts.map +1 -0
  373. package/dist/catalog/images/fairy-caves/treehouse-2.js +8 -0
  374. package/dist/catalog/images/fairy-caves/treehouse-2.js.map +1 -0
  375. package/dist/catalog/images/fairy-caves/treehouse-2.thumb.webp +0 -0
  376. package/dist/catalog/images/fairy-caves/treehouse-2.web.d.ts +3 -0
  377. package/dist/catalog/images/fairy-caves/treehouse-2.web.d.ts.map +1 -0
  378. package/dist/catalog/images/fairy-caves/treehouse-2.web.js +12 -0
  379. package/dist/catalog/images/fairy-caves/treehouse-2.web.js.map +1 -0
  380. package/dist/catalog/images/fairy-caves/treehouse-2.webp +0 -0
  381. package/dist/catalog/images/fairy-caves/treehouse-3.d.ts +3 -0
  382. package/dist/catalog/images/fairy-caves/treehouse-3.d.ts.map +1 -0
  383. package/dist/catalog/images/fairy-caves/treehouse-3.js +8 -0
  384. package/dist/catalog/images/fairy-caves/treehouse-3.js.map +1 -0
  385. package/dist/catalog/images/fairy-caves/treehouse-3.thumb.webp +0 -0
  386. package/dist/catalog/images/fairy-caves/treehouse-3.web.d.ts +3 -0
  387. package/dist/catalog/images/fairy-caves/treehouse-3.web.d.ts.map +1 -0
  388. package/dist/catalog/images/fairy-caves/treehouse-3.web.js +12 -0
  389. package/dist/catalog/images/fairy-caves/treehouse-3.web.js.map +1 -0
  390. package/dist/catalog/images/fairy-caves/treehouse-3.webp +0 -0
  391. package/dist/catalog/images/fairy-caves/treehouse.d.ts +3 -0
  392. package/dist/catalog/images/fairy-caves/treehouse.d.ts.map +1 -0
  393. package/dist/catalog/images/fairy-caves/treehouse.js +8 -0
  394. package/dist/catalog/images/fairy-caves/treehouse.js.map +1 -0
  395. package/dist/catalog/images/fairy-caves/treehouse.thumb.webp +0 -0
  396. package/dist/catalog/images/fairy-caves/treehouse.web.d.ts +3 -0
  397. package/dist/catalog/images/fairy-caves/treehouse.web.d.ts.map +1 -0
  398. package/dist/catalog/images/fairy-caves/treehouse.web.js +12 -0
  399. package/dist/catalog/images/fairy-caves/treehouse.web.js.map +1 -0
  400. package/dist/catalog/images/fairy-caves/treehouse.webp +0 -0
  401. package/dist/catalog/images/home/home-dark.d.ts +3 -0
  402. package/dist/catalog/images/home/home-dark.d.ts.map +1 -0
  403. package/dist/catalog/images/home/home-dark.js +8 -0
  404. package/dist/catalog/images/home/home-dark.js.map +1 -0
  405. package/dist/catalog/images/home/home-dark.thumb.webp +0 -0
  406. package/dist/catalog/images/home/home-dark.web.d.ts +3 -0
  407. package/dist/catalog/images/home/home-dark.web.d.ts.map +1 -0
  408. package/dist/catalog/images/home/home-dark.web.js +12 -0
  409. package/dist/catalog/images/home/home-dark.web.js.map +1 -0
  410. package/dist/catalog/images/home/home-light.d.ts +3 -0
  411. package/dist/catalog/images/home/home-light.d.ts.map +1 -0
  412. package/dist/catalog/images/home/home-light.js +8 -0
  413. package/dist/catalog/images/home/home-light.js.map +1 -0
  414. package/dist/catalog/images/home/home-light.thumb.webp +0 -0
  415. package/dist/catalog/images/home/home-light.web.d.ts +3 -0
  416. package/dist/catalog/images/home/home-light.web.d.ts.map +1 -0
  417. package/dist/catalog/images/home/home-light.web.js +12 -0
  418. package/dist/catalog/images/home/home-light.web.js.map +1 -0
  419. package/dist/catalog/images/image-ids.d.ts +3 -0
  420. package/dist/catalog/images/image-ids.d.ts.map +1 -0
  421. package/dist/catalog/images/image-ids.js +43 -0
  422. package/dist/catalog/images/image-ids.js.map +1 -0
  423. package/dist/catalog/images/image.types.d.ts +2 -0
  424. package/dist/catalog/images/image.types.d.ts.map +1 -0
  425. package/dist/catalog/images/image.types.js +3 -0
  426. package/dist/catalog/images/image.types.js.map +1 -0
  427. package/dist/catalog/images/index.d.ts +3 -0
  428. package/dist/catalog/images/index.d.ts.map +1 -0
  429. package/dist/catalog/images/index.js +10 -0
  430. package/dist/catalog/images/index.js.map +1 -0
  431. package/dist/catalog/images/nature/landscape-dark.d.ts +3 -0
  432. package/dist/catalog/images/nature/landscape-dark.d.ts.map +1 -0
  433. package/dist/catalog/images/nature/landscape-dark.js +8 -0
  434. package/dist/catalog/images/nature/landscape-dark.js.map +1 -0
  435. package/dist/catalog/images/nature/landscape-dark.thumb.webp +0 -0
  436. package/dist/catalog/images/nature/landscape-dark.web.d.ts +3 -0
  437. package/dist/catalog/images/nature/landscape-dark.web.d.ts.map +1 -0
  438. package/dist/catalog/images/nature/landscape-dark.web.js +12 -0
  439. package/dist/catalog/images/nature/landscape-dark.web.js.map +1 -0
  440. package/dist/catalog/images/nature/landscape-light.d.ts +3 -0
  441. package/dist/catalog/images/nature/landscape-light.d.ts.map +1 -0
  442. package/dist/catalog/images/nature/landscape-light.js +8 -0
  443. package/dist/catalog/images/nature/landscape-light.js.map +1 -0
  444. package/dist/catalog/images/nature/landscape-light.thumb.webp +0 -0
  445. package/dist/catalog/images/nature/landscape-light.web.d.ts +3 -0
  446. package/dist/catalog/images/nature/landscape-light.web.d.ts.map +1 -0
  447. package/dist/catalog/images/nature/landscape-light.web.js +12 -0
  448. package/dist/catalog/images/nature/landscape-light.web.js.map +1 -0
  449. package/dist/catalog/images/office/office-dark.d.ts +3 -0
  450. package/dist/catalog/images/office/office-dark.d.ts.map +1 -0
  451. package/dist/catalog/images/office/office-dark.js +8 -0
  452. package/dist/catalog/images/office/office-dark.js.map +1 -0
  453. package/dist/catalog/images/office/office-dark.thumb.webp +0 -0
  454. package/dist/catalog/images/office/office-dark.web.d.ts +3 -0
  455. package/dist/catalog/images/office/office-dark.web.d.ts.map +1 -0
  456. package/dist/catalog/images/office/office-dark.web.js +12 -0
  457. package/dist/catalog/images/office/office-dark.web.js.map +1 -0
  458. package/dist/catalog/images/office/office-light.d.ts +3 -0
  459. package/dist/catalog/images/office/office-light.d.ts.map +1 -0
  460. package/dist/catalog/images/office/office-light.js +8 -0
  461. package/dist/catalog/images/office/office-light.js.map +1 -0
  462. package/dist/catalog/images/office/office-light.thumb.webp +0 -0
  463. package/dist/catalog/images/office/office-light.web.d.ts +3 -0
  464. package/dist/catalog/images/office/office-light.web.d.ts.map +1 -0
  465. package/dist/catalog/images/office/office-light.web.js +12 -0
  466. package/dist/catalog/images/office/office-light.web.js.map +1 -0
  467. package/dist/catalog/images/sci-fi/sci-fi-light.d.ts +3 -0
  468. package/dist/catalog/images/sci-fi/sci-fi-light.d.ts.map +1 -0
  469. package/dist/catalog/images/sci-fi/sci-fi-light.js +8 -0
  470. package/dist/catalog/images/sci-fi/sci-fi-light.js.map +1 -0
  471. package/dist/catalog/images/sci-fi/sci-fi-light.thumb.webp +0 -0
  472. package/dist/catalog/images/sci-fi/sci-fi-light.web.d.ts +3 -0
  473. package/dist/catalog/images/sci-fi/sci-fi-light.web.d.ts.map +1 -0
  474. package/dist/catalog/images/sci-fi/sci-fi-light.web.js +12 -0
  475. package/dist/catalog/images/sci-fi/sci-fi-light.web.js.map +1 -0
  476. package/dist/catalog/images/simiancraft/simiancraft-dark-transparency.d.ts +3 -0
  477. package/dist/catalog/images/simiancraft/simiancraft-dark-transparency.d.ts.map +1 -0
  478. package/dist/catalog/images/simiancraft/simiancraft-dark-transparency.js +8 -0
  479. package/dist/catalog/images/simiancraft/simiancraft-dark-transparency.js.map +1 -0
  480. package/dist/catalog/images/simiancraft/simiancraft-dark-transparency.thumb.webp +0 -0
  481. package/dist/catalog/images/simiancraft/simiancraft-dark-transparency.web.d.ts +3 -0
  482. package/dist/catalog/images/simiancraft/simiancraft-dark-transparency.web.d.ts.map +1 -0
  483. package/dist/catalog/images/simiancraft/simiancraft-dark-transparency.web.js +12 -0
  484. package/dist/catalog/images/simiancraft/simiancraft-dark-transparency.web.js.map +1 -0
  485. package/dist/catalog/images/simiancraft/simiancraft-dark-transparency.webp +0 -0
  486. package/dist/catalog/images/simiancraft/simiancraft-dark.d.ts +3 -0
  487. package/dist/catalog/images/simiancraft/simiancraft-dark.d.ts.map +1 -0
  488. package/dist/catalog/images/simiancraft/simiancraft-dark.js +8 -0
  489. package/dist/catalog/images/simiancraft/simiancraft-dark.js.map +1 -0
  490. package/dist/catalog/images/simiancraft/simiancraft-dark.thumb.webp +0 -0
  491. package/dist/catalog/images/simiancraft/simiancraft-dark.web.d.ts +3 -0
  492. package/dist/catalog/images/simiancraft/simiancraft-dark.web.d.ts.map +1 -0
  493. package/dist/catalog/images/simiancraft/simiancraft-dark.web.js +12 -0
  494. package/dist/catalog/images/simiancraft/simiancraft-dark.web.js.map +1 -0
  495. package/dist/catalog/images/simiancraft/simiancraft-light-transparency.d.ts +3 -0
  496. package/dist/catalog/images/simiancraft/simiancraft-light-transparency.d.ts.map +1 -0
  497. package/dist/catalog/images/simiancraft/simiancraft-light-transparency.js +8 -0
  498. package/dist/catalog/images/simiancraft/simiancraft-light-transparency.js.map +1 -0
  499. package/dist/catalog/images/simiancraft/simiancraft-light-transparency.thumb.webp +0 -0
  500. package/dist/catalog/images/simiancraft/simiancraft-light-transparency.web.d.ts +3 -0
  501. package/dist/catalog/images/simiancraft/simiancraft-light-transparency.web.d.ts.map +1 -0
  502. package/dist/catalog/images/simiancraft/simiancraft-light-transparency.web.js +12 -0
  503. package/dist/catalog/images/simiancraft/simiancraft-light-transparency.web.js.map +1 -0
  504. package/dist/catalog/images/simiancraft/simiancraft-light-transparency.webp +0 -0
  505. package/dist/catalog/images/simiancraft/simiancraft-light.d.ts +3 -0
  506. package/dist/catalog/images/simiancraft/simiancraft-light.d.ts.map +1 -0
  507. package/dist/catalog/images/simiancraft/simiancraft-light.js +8 -0
  508. package/dist/catalog/images/simiancraft/simiancraft-light.js.map +1 -0
  509. package/dist/catalog/images/simiancraft/simiancraft-light.thumb.webp +0 -0
  510. package/dist/catalog/images/simiancraft/simiancraft-light.web.d.ts +3 -0
  511. package/dist/catalog/images/simiancraft/simiancraft-light.web.d.ts.map +1 -0
  512. package/dist/catalog/images/simiancraft/simiancraft-light.web.js +12 -0
  513. package/dist/catalog/images/simiancraft/simiancraft-light.web.js.map +1 -0
  514. package/dist/catalog/images/spaceship/observation-deck.d.ts +3 -0
  515. package/dist/catalog/images/spaceship/observation-deck.d.ts.map +1 -0
  516. package/dist/catalog/images/spaceship/observation-deck.js +8 -0
  517. package/dist/catalog/images/spaceship/observation-deck.js.map +1 -0
  518. package/dist/catalog/images/spaceship/observation-deck.thumb.webp +0 -0
  519. package/dist/catalog/images/spaceship/observation-deck.web.d.ts +3 -0
  520. package/dist/catalog/images/spaceship/observation-deck.web.d.ts.map +1 -0
  521. package/dist/catalog/images/spaceship/observation-deck.web.js +12 -0
  522. package/dist/catalog/images/spaceship/observation-deck.web.js.map +1 -0
  523. package/dist/catalog/images/spaceship/observation-deck.webp +0 -0
  524. package/dist/catalog/images/underwater/oceanscape-dark.d.ts +3 -0
  525. package/dist/catalog/images/underwater/oceanscape-dark.d.ts.map +1 -0
  526. package/dist/catalog/images/underwater/oceanscape-dark.js +8 -0
  527. package/dist/catalog/images/underwater/oceanscape-dark.js.map +1 -0
  528. package/dist/catalog/images/underwater/oceanscape-dark.thumb.webp +0 -0
  529. package/dist/catalog/images/underwater/oceanscape-dark.web.d.ts +3 -0
  530. package/dist/catalog/images/underwater/oceanscape-dark.web.d.ts.map +1 -0
  531. package/dist/catalog/images/underwater/oceanscape-dark.web.js +12 -0
  532. package/dist/catalog/images/underwater/oceanscape-dark.web.js.map +1 -0
  533. package/dist/catalog/images/underwater/oceanscape-dark.webp +0 -0
  534. package/dist/catalog/images/wizard-tower/wizard-tower-1.d.ts +3 -0
  535. package/dist/catalog/images/wizard-tower/wizard-tower-1.d.ts.map +1 -0
  536. package/dist/catalog/images/wizard-tower/wizard-tower-1.js +8 -0
  537. package/dist/catalog/images/wizard-tower/wizard-tower-1.js.map +1 -0
  538. package/dist/catalog/images/wizard-tower/wizard-tower-1.thumb.webp +0 -0
  539. package/dist/catalog/images/wizard-tower/wizard-tower-1.web.d.ts +3 -0
  540. package/dist/catalog/images/wizard-tower/wizard-tower-1.web.d.ts.map +1 -0
  541. package/dist/catalog/images/wizard-tower/wizard-tower-1.web.js +12 -0
  542. package/dist/catalog/images/wizard-tower/wizard-tower-1.web.js.map +1 -0
  543. package/dist/catalog/images/wizard-tower/wizard-tower-1.webp +0 -0
  544. package/dist/catalog/images/wizard-tower/wizard-tower-2.d.ts +3 -0
  545. package/dist/catalog/images/wizard-tower/wizard-tower-2.d.ts.map +1 -0
  546. package/dist/catalog/images/wizard-tower/wizard-tower-2.js +8 -0
  547. package/dist/catalog/images/wizard-tower/wizard-tower-2.js.map +1 -0
  548. package/dist/catalog/images/wizard-tower/wizard-tower-2.thumb.webp +0 -0
  549. package/dist/catalog/images/wizard-tower/wizard-tower-2.web.d.ts +3 -0
  550. package/dist/catalog/images/wizard-tower/wizard-tower-2.web.d.ts.map +1 -0
  551. package/dist/catalog/images/wizard-tower/wizard-tower-2.web.js +12 -0
  552. package/dist/catalog/images/wizard-tower/wizard-tower-2.web.js.map +1 -0
  553. package/dist/catalog/images/wizard-tower/wizard-tower-2.webp +0 -0
  554. package/dist/catalog/images/wizard-tower/wizard-tower-night.d.ts +3 -0
  555. package/dist/catalog/images/wizard-tower/wizard-tower-night.d.ts.map +1 -0
  556. package/dist/catalog/images/wizard-tower/wizard-tower-night.js +8 -0
  557. package/dist/catalog/images/wizard-tower/wizard-tower-night.js.map +1 -0
  558. package/dist/catalog/images/wizard-tower/wizard-tower-night.thumb.webp +0 -0
  559. package/dist/catalog/images/wizard-tower/wizard-tower-night.web.d.ts +3 -0
  560. package/dist/catalog/images/wizard-tower/wizard-tower-night.web.d.ts.map +1 -0
  561. package/dist/catalog/images/wizard-tower/wizard-tower-night.web.js +12 -0
  562. package/dist/catalog/images/wizard-tower/wizard-tower-night.web.js.map +1 -0
  563. package/dist/catalog/images/wizard-tower/wizard-tower-night.webp +0 -0
  564. package/dist/catalog/shaders/_shared/types.d.ts +38 -0
  565. package/dist/catalog/shaders/_shared/types.d.ts.map +1 -0
  566. package/dist/catalog/shaders/_shared/types.js +15 -0
  567. package/dist/catalog/shaders/_shared/types.js.map +1 -0
  568. package/dist/catalog/shaders/anamorphic-lensflare/anamorphic-lensflare.d.ts +26 -0
  569. package/dist/catalog/shaders/anamorphic-lensflare/anamorphic-lensflare.d.ts.map +1 -0
  570. package/dist/catalog/shaders/anamorphic-lensflare/anamorphic-lensflare.form.d.ts +3 -0
  571. package/dist/catalog/shaders/anamorphic-lensflare/anamorphic-lensflare.form.d.ts.map +1 -0
  572. package/dist/catalog/shaders/anamorphic-lensflare/anamorphic-lensflare.form.js +15 -0
  573. package/dist/catalog/shaders/anamorphic-lensflare/anamorphic-lensflare.form.js.map +1 -0
  574. package/dist/catalog/shaders/anamorphic-lensflare/anamorphic-lensflare.js +84 -0
  575. package/dist/catalog/shaders/anamorphic-lensflare/anamorphic-lensflare.js.map +1 -0
  576. package/dist/catalog/shaders/blur/blur.d.ts +15 -0
  577. package/dist/catalog/shaders/blur/blur.d.ts.map +1 -0
  578. package/dist/catalog/shaders/blur/blur.form.d.ts +3 -0
  579. package/dist/catalog/shaders/blur/blur.form.d.ts.map +1 -0
  580. package/dist/catalog/shaders/blur/blur.form.js +15 -0
  581. package/dist/catalog/shaders/blur/blur.form.js.map +1 -0
  582. package/dist/catalog/shaders/blur/blur.js +27 -0
  583. package/dist/catalog/shaders/blur/blur.js.map +1 -0
  584. package/dist/catalog/shaders/clouds/clouds.d.ts +34 -0
  585. package/dist/catalog/shaders/clouds/clouds.d.ts.map +1 -0
  586. package/dist/catalog/shaders/clouds/clouds.form.d.ts +3 -0
  587. package/dist/catalog/shaders/clouds/clouds.form.d.ts.map +1 -0
  588. package/dist/catalog/shaders/clouds/clouds.form.js +15 -0
  589. package/dist/catalog/shaders/clouds/clouds.form.js.map +1 -0
  590. package/dist/catalog/shaders/clouds/clouds.js +98 -0
  591. package/dist/catalog/shaders/clouds/clouds.js.map +1 -0
  592. package/dist/catalog/shaders/corporate-blobs/corporate-blobs.d.ts +40 -0
  593. package/dist/catalog/shaders/corporate-blobs/corporate-blobs.d.ts.map +1 -0
  594. package/dist/catalog/shaders/corporate-blobs/corporate-blobs.form.d.ts +3 -0
  595. package/dist/catalog/shaders/corporate-blobs/corporate-blobs.form.d.ts.map +1 -0
  596. package/dist/catalog/shaders/corporate-blobs/corporate-blobs.form.js +15 -0
  597. package/dist/catalog/shaders/corporate-blobs/corporate-blobs.form.js.map +1 -0
  598. package/dist/catalog/shaders/corporate-blobs/corporate-blobs.js +100 -0
  599. package/dist/catalog/shaders/corporate-blobs/corporate-blobs.js.map +1 -0
  600. package/dist/catalog/shaders/fireflies/fireflies.d.ts +18 -0
  601. package/dist/catalog/shaders/fireflies/fireflies.d.ts.map +1 -0
  602. package/dist/catalog/shaders/fireflies/fireflies.form.d.ts +3 -0
  603. package/dist/catalog/shaders/fireflies/fireflies.form.d.ts.map +1 -0
  604. package/dist/catalog/shaders/fireflies/fireflies.form.js +15 -0
  605. package/dist/catalog/shaders/fireflies/fireflies.form.js.map +1 -0
  606. package/dist/catalog/shaders/fireflies/fireflies.js +47 -0
  607. package/dist/catalog/shaders/fireflies/fireflies.js.map +1 -0
  608. package/dist/catalog/shaders/godrays/godrays.d.ts +26 -0
  609. package/dist/catalog/shaders/godrays/godrays.d.ts.map +1 -0
  610. package/dist/catalog/shaders/godrays/godrays.form.d.ts +3 -0
  611. package/dist/catalog/shaders/godrays/godrays.form.d.ts.map +1 -0
  612. package/dist/catalog/shaders/godrays/godrays.form.js +15 -0
  613. package/dist/catalog/shaders/godrays/godrays.form.js.map +1 -0
  614. package/dist/catalog/shaders/godrays/godrays.js +83 -0
  615. package/dist/catalog/shaders/godrays/godrays.js.map +1 -0
  616. package/dist/catalog/shaders/index.d.ts +73 -0
  617. package/dist/catalog/shaders/index.d.ts.map +1 -0
  618. package/dist/catalog/shaders/index.js +30 -0
  619. package/dist/catalog/shaders/index.js.map +1 -0
  620. package/dist/catalog/shaders/light-beams-and-motes/light-beams-and-motes.d.ts +44 -0
  621. package/dist/catalog/shaders/light-beams-and-motes/light-beams-and-motes.d.ts.map +1 -0
  622. package/dist/catalog/shaders/light-beams-and-motes/light-beams-and-motes.form.d.ts +3 -0
  623. package/dist/catalog/shaders/light-beams-and-motes/light-beams-and-motes.form.d.ts.map +1 -0
  624. package/dist/catalog/shaders/light-beams-and-motes/light-beams-and-motes.form.js +16 -0
  625. package/dist/catalog/shaders/light-beams-and-motes/light-beams-and-motes.form.js.map +1 -0
  626. package/dist/catalog/shaders/light-beams-and-motes/light-beams-and-motes.js +91 -0
  627. package/dist/catalog/shaders/light-beams-and-motes/light-beams-and-motes.js.map +1 -0
  628. package/dist/catalog/shaders/nebula/nebula.d.ts +20 -0
  629. package/dist/catalog/shaders/nebula/nebula.d.ts.map +1 -0
  630. package/dist/catalog/shaders/nebula/nebula.form.d.ts +3 -0
  631. package/dist/catalog/shaders/nebula/nebula.form.d.ts.map +1 -0
  632. package/dist/catalog/shaders/nebula/nebula.form.js +15 -0
  633. package/dist/catalog/shaders/nebula/nebula.form.js.map +1 -0
  634. package/dist/catalog/shaders/nebula/nebula.js +58 -0
  635. package/dist/catalog/shaders/nebula/nebula.js.map +1 -0
  636. package/dist/catalog/shaders/plasma/plasma.d.ts +16 -0
  637. package/dist/catalog/shaders/plasma/plasma.d.ts.map +1 -0
  638. package/dist/catalog/shaders/plasma/plasma.form.d.ts +3 -0
  639. package/dist/catalog/shaders/plasma/plasma.form.d.ts.map +1 -0
  640. package/dist/catalog/shaders/plasma/plasma.form.js +15 -0
  641. package/dist/catalog/shaders/plasma/plasma.form.js.map +1 -0
  642. package/dist/catalog/shaders/plasma/plasma.js +32 -0
  643. package/dist/catalog/shaders/plasma/plasma.js.map +1 -0
  644. package/dist/catalog/shaders/simianlights/simianlights.d.ts +20 -0
  645. package/dist/catalog/shaders/simianlights/simianlights.d.ts.map +1 -0
  646. package/dist/catalog/shaders/simianlights/simianlights.form.d.ts +3 -0
  647. package/dist/catalog/shaders/simianlights/simianlights.form.d.ts.map +1 -0
  648. package/dist/catalog/shaders/simianlights/simianlights.form.js +15 -0
  649. package/dist/catalog/shaders/simianlights/simianlights.form.js.map +1 -0
  650. package/dist/catalog/shaders/simianlights/simianlights.js +57 -0
  651. package/dist/catalog/shaders/simianlights/simianlights.js.map +1 -0
  652. package/dist/src/components/form/control-form.d.ts +37 -0
  653. package/dist/src/components/form/control-form.d.ts.map +1 -0
  654. package/dist/src/components/form/control-form.js +55 -0
  655. package/dist/src/components/form/control-form.js.map +1 -0
  656. package/dist/src/components/form/make-controls.d.ts +22 -0
  657. package/dist/src/components/form/make-controls.d.ts.map +1 -0
  658. package/dist/src/components/form/make-controls.js +19 -0
  659. package/dist/src/components/form/make-controls.js.map +1 -0
  660. package/dist/src/components/form/scope.d.ts +2 -0
  661. package/dist/src/components/form/scope.d.ts.map +1 -0
  662. package/dist/src/components/form/scope.js +11 -0
  663. package/dist/src/components/form/scope.js.map +1 -0
  664. package/dist/src/components/form/use-field.d.ts +10 -0
  665. package/dist/src/components/form/use-field.d.ts.map +1 -0
  666. package/dist/src/components/form/use-field.js +27 -0
  667. package/dist/src/components/form/use-field.js.map +1 -0
  668. package/dist/src/components/preset-book-menu/index.d.ts +52 -0
  669. package/dist/src/components/preset-book-menu/index.d.ts.map +1 -0
  670. package/dist/src/components/preset-book-menu/index.js +152 -0
  671. package/dist/src/components/preset-book-menu/index.js.map +1 -0
  672. package/dist/src/components/preset-book-menu/layout.d.ts +25 -0
  673. package/dist/src/components/preset-book-menu/layout.d.ts.map +1 -0
  674. package/dist/src/components/preset-book-menu/layout.js +19 -0
  675. package/dist/src/components/preset-book-menu/layout.js.map +1 -0
  676. package/dist/src/components/preset-book-menu/preset-book-menu.types.d.ts +88 -0
  677. package/dist/src/components/preset-book-menu/preset-book-menu.types.d.ts.map +1 -0
  678. package/dist/src/components/preset-book-menu/preset-book-menu.types.js +14 -0
  679. package/dist/src/components/preset-book-menu/preset-book-menu.types.js.map +1 -0
  680. package/dist/src/components/preset-book-menu/preset-grid.d.ts +16 -0
  681. package/dist/src/components/preset-book-menu/preset-grid.d.ts.map +1 -0
  682. package/dist/src/components/preset-book-menu/preset-grid.js +49 -0
  683. package/dist/src/components/preset-book-menu/preset-grid.js.map +1 -0
  684. package/dist/src/components/preset-book-menu/resolve-image-uri.d.ts +3 -0
  685. package/dist/src/components/preset-book-menu/resolve-image-uri.d.ts.map +1 -0
  686. package/dist/src/components/preset-book-menu/resolve-image-uri.js +28 -0
  687. package/dist/src/components/preset-book-menu/resolve-image-uri.js.map +1 -0
  688. package/dist/src/components/preset-book-menu/resolve-image-uri.types.d.ts +13 -0
  689. package/dist/src/components/preset-book-menu/resolve-image-uri.types.d.ts.map +1 -0
  690. package/dist/src/components/preset-book-menu/resolve-image-uri.types.js +5 -0
  691. package/dist/src/components/preset-book-menu/resolve-image-uri.types.js.map +1 -0
  692. package/dist/src/components/preset-book-menu/resolve-image-uri.web.d.ts +3 -0
  693. package/dist/src/components/preset-book-menu/resolve-image-uri.web.d.ts.map +1 -0
  694. package/dist/src/components/preset-book-menu/resolve-image-uri.web.js +17 -0
  695. package/dist/src/components/preset-book-menu/resolve-image-uri.web.js.map +1 -0
  696. package/dist/src/components/preset-control-panel/composite-layer-control-panel.d.ts +14 -0
  697. package/dist/src/components/preset-control-panel/composite-layer-control-panel.d.ts.map +1 -0
  698. package/dist/src/components/preset-control-panel/composite-layer-control-panel.js +36 -0
  699. package/dist/src/components/preset-control-panel/composite-layer-control-panel.js.map +1 -0
  700. package/dist/src/components/preset-control-panel/control-section.d.ts +9 -0
  701. package/dist/src/components/preset-control-panel/control-section.d.ts.map +1 -0
  702. package/dist/src/components/preset-control-panel/control-section.js +47 -0
  703. package/dist/src/components/preset-control-panel/control-section.js.map +1 -0
  704. package/dist/src/components/preset-control-panel/control.d.ts +10 -0
  705. package/dist/src/components/preset-control-panel/control.d.ts.map +1 -0
  706. package/dist/src/components/preset-control-panel/control.js +35 -0
  707. package/dist/src/components/preset-control-panel/control.js.map +1 -0
  708. package/dist/src/components/preset-control-panel/index.d.ts +14 -0
  709. package/dist/src/components/preset-control-panel/index.d.ts.map +1 -0
  710. package/dist/src/components/preset-control-panel/index.js +49 -0
  711. package/dist/src/components/preset-control-panel/index.js.map +1 -0
  712. package/dist/src/components/preset-control-panel/mask-control-panel.d.ts +11 -0
  713. package/dist/src/components/preset-control-panel/mask-control-panel.d.ts.map +1 -0
  714. package/dist/src/components/preset-control-panel/mask-control-panel.js +34 -0
  715. package/dist/src/components/preset-control-panel/mask-control-panel.js.map +1 -0
  716. package/dist/src/components/preset-control-panel/preset-control-panel.d.ts +12 -0
  717. package/dist/src/components/preset-control-panel/preset-control-panel.d.ts.map +1 -0
  718. package/dist/src/components/preset-control-panel/preset-control-panel.js +23 -0
  719. package/dist/src/components/preset-control-panel/preset-control-panel.js.map +1 -0
  720. package/dist/src/components/preset-control-panel/transform-control-panel.d.ts +14 -0
  721. package/dist/src/components/preset-control-panel/transform-control-panel.d.ts.map +1 -0
  722. package/dist/src/components/preset-control-panel/transform-control-panel.js +58 -0
  723. package/dist/src/components/preset-control-panel/transform-control-panel.js.map +1 -0
  724. package/dist/src/components/preset-tile/index.d.ts +24 -0
  725. package/dist/src/components/preset-tile/index.d.ts.map +1 -0
  726. package/dist/src/components/preset-tile/index.js +98 -0
  727. package/dist/src/components/preset-tile/index.js.map +1 -0
  728. package/dist/src/components/theme/provider.d.ts +18 -0
  729. package/dist/src/components/theme/provider.d.ts.map +1 -0
  730. package/dist/src/components/theme/provider.js +29 -0
  731. package/dist/src/components/theme/provider.js.map +1 -0
  732. package/dist/src/components/theme/slots.d.ts +17 -0
  733. package/dist/src/components/theme/slots.d.ts.map +1 -0
  734. package/dist/src/components/theme/slots.js +9 -0
  735. package/dist/src/components/theme/slots.js.map +1 -0
  736. package/dist/src/components/ui/button.d.ts +14 -0
  737. package/dist/src/components/ui/button.d.ts.map +1 -0
  738. package/dist/src/components/ui/button.js +29 -0
  739. package/dist/src/components/ui/button.js.map +1 -0
  740. package/dist/src/components/ui/color-picker.d.ts +12 -0
  741. package/dist/src/components/ui/color-picker.d.ts.map +1 -0
  742. package/dist/src/components/ui/color-picker.js +43 -0
  743. package/dist/src/components/ui/color-picker.js.map +1 -0
  744. package/dist/src/components/ui/index.d.ts +6 -0
  745. package/dist/src/components/ui/index.d.ts.map +1 -0
  746. package/dist/src/components/ui/index.js +18 -0
  747. package/dist/src/components/ui/index.js.map +1 -0
  748. package/dist/src/components/ui/label.d.ts +10 -0
  749. package/dist/src/components/ui/label.d.ts.map +1 -0
  750. package/dist/src/components/ui/label.js +14 -0
  751. package/dist/src/components/ui/label.js.map +1 -0
  752. package/dist/src/components/ui/point.d.ts +19 -0
  753. package/dist/src/components/ui/point.d.ts.map +1 -0
  754. package/dist/src/components/ui/point.js +52 -0
  755. package/dist/src/components/ui/point.js.map +1 -0
  756. package/dist/src/components/ui/polygon-field.d.ts +10 -0
  757. package/dist/src/components/ui/polygon-field.d.ts.map +1 -0
  758. package/dist/src/components/ui/polygon-field.js +50 -0
  759. package/dist/src/components/ui/polygon-field.js.map +1 -0
  760. package/dist/src/components/ui/readout.d.ts +10 -0
  761. package/dist/src/components/ui/readout.d.ts.map +1 -0
  762. package/dist/src/components/ui/readout.js +14 -0
  763. package/dist/src/components/ui/readout.js.map +1 -0
  764. package/dist/src/components/ui/slider-value.d.ts +8 -0
  765. package/dist/src/components/ui/slider-value.d.ts.map +1 -0
  766. package/dist/src/components/ui/slider-value.js +17 -0
  767. package/dist/src/components/ui/slider-value.js.map +1 -0
  768. package/dist/src/components/ui/slider.d.ts +15 -0
  769. package/dist/src/components/ui/slider.d.ts.map +1 -0
  770. package/dist/src/components/ui/slider.js +58 -0
  771. package/dist/src/components/ui/slider.js.map +1 -0
  772. package/dist/src/components/ui/switch.d.ts +8 -0
  773. package/dist/src/components/ui/switch.d.ts.map +1 -0
  774. package/dist/src/components/ui/switch.js +24 -0
  775. package/dist/src/components/ui/switch.js.map +1 -0
  776. package/dist/src/index.d.ts +18 -0
  777. package/dist/src/index.d.ts.map +1 -0
  778. package/dist/src/index.js +187 -0
  779. package/dist/src/index.js.map +1 -0
  780. package/dist/src/index.web.d.ts +32 -0
  781. package/dist/src/index.web.d.ts.map +1 -0
  782. package/dist/src/index.web.js +119 -0
  783. package/dist/src/index.web.js.map +1 -0
  784. package/dist/src/kaleidoscope/controls.d.ts +24 -0
  785. package/dist/src/kaleidoscope/controls.d.ts.map +1 -0
  786. package/dist/src/kaleidoscope/controls.js +92 -0
  787. package/dist/src/kaleidoscope/controls.js.map +1 -0
  788. package/dist/src/kaleidoscope/effect.d.ts +4 -0
  789. package/dist/src/kaleidoscope/effect.d.ts.map +1 -0
  790. package/dist/src/kaleidoscope/effect.js +7 -0
  791. package/dist/src/kaleidoscope/effect.js.map +1 -0
  792. package/dist/src/kaleidoscope/effect.types.d.ts +47 -0
  793. package/dist/src/kaleidoscope/effect.types.d.ts.map +1 -0
  794. package/dist/src/kaleidoscope/effect.types.js +9 -0
  795. package/dist/src/kaleidoscope/effect.types.js.map +1 -0
  796. package/dist/src/kaleidoscope/shader-to-spec.d.ts +4 -0
  797. package/dist/src/kaleidoscope/shader-to-spec.d.ts.map +1 -0
  798. package/dist/src/kaleidoscope/shader-to-spec.js +17 -0
  799. package/dist/src/kaleidoscope/shader-to-spec.js.map +1 -0
  800. package/dist/src/kaleidoscope/types.d.ts +79 -0
  801. package/dist/src/kaleidoscope/types.d.ts.map +1 -0
  802. package/dist/src/kaleidoscope/types.js +18 -0
  803. package/dist/src/kaleidoscope/types.js.map +1 -0
  804. package/dist/src/kaleidoscope.preset-book.types.d.ts +86 -0
  805. package/dist/src/kaleidoscope.preset-book.types.d.ts.map +1 -0
  806. package/dist/src/kaleidoscope.preset-book.types.js +16 -0
  807. package/dist/src/kaleidoscope.preset-book.types.js.map +1 -0
  808. package/dist/src/lib/primitives.types.d.ts +3 -0
  809. package/dist/src/lib/primitives.types.d.ts.map +1 -0
  810. package/dist/src/lib/primitives.types.js +5 -0
  811. package/dist/src/lib/primitives.types.js.map +1 -0
  812. package/dist/src/lib/test-id.d.ts +30 -0
  813. package/dist/src/lib/test-id.d.ts.map +1 -0
  814. package/dist/src/lib/test-id.js +81 -0
  815. package/dist/src/lib/test-id.js.map +1 -0
  816. package/dist/src/livekit.d.ts +24 -0
  817. package/dist/src/livekit.d.ts.map +1 -0
  818. package/dist/src/livekit.js +63 -0
  819. package/dist/src/livekit.js.map +1 -0
  820. package/dist/src/nativewind.d.ts +7 -0
  821. package/dist/src/nativewind.d.ts.map +1 -0
  822. package/dist/src/nativewind.js +43 -0
  823. package/dist/src/nativewind.js.map +1 -0
  824. package/dist/web-driver/effects/composite.d.ts +14 -0
  825. package/dist/web-driver/effects/composite.d.ts.map +1 -0
  826. package/dist/web-driver/effects/composite.js +576 -0
  827. package/dist/web-driver/effects/composite.js.map +1 -0
  828. package/dist/web-driver/effects/layer-shaders.d.ts +2 -0
  829. package/dist/web-driver/effects/layer-shaders.d.ts.map +1 -0
  830. package/dist/web-driver/effects/layer-shaders.js +11 -0
  831. package/dist/web-driver/effects/layer-shaders.js.map +1 -0
  832. package/dist/web-driver/effects/transform.d.ts +4 -0
  833. package/dist/web-driver/effects/transform.d.ts.map +1 -0
  834. package/dist/web-driver/effects/transform.js +66 -0
  835. package/dist/web-driver/effects/transform.js.map +1 -0
  836. package/dist/web-driver/index.d.ts +6 -0
  837. package/dist/web-driver/index.d.ts.map +1 -0
  838. package/dist/web-driver/index.js +21 -0
  839. package/dist/web-driver/index.js.map +1 -0
  840. package/dist/web-driver/insertable-streams.d.ts.map +1 -0
  841. package/dist/web-driver/insertable-streams.js +68 -0
  842. package/dist/web-driver/insertable-streams.js.map +1 -0
  843. package/dist/web-driver/segmenter.d.ts.map +1 -0
  844. package/dist/web-driver/segmenter.js +89 -0
  845. package/dist/web-driver/segmenter.js.map +1 -0
  846. package/dist/web-driver/shaders.d.ts +2 -0
  847. package/dist/web-driver/shaders.d.ts.map +1 -0
  848. package/dist/web-driver/shaders.generated.d.ts +17 -0
  849. package/dist/web-driver/shaders.generated.d.ts.map +1 -0
  850. package/dist/web-driver/shaders.generated.js +1180 -0
  851. package/dist/web-driver/shaders.generated.js.map +1 -0
  852. package/dist/web-driver/shaders.js +28 -0
  853. package/dist/web-driver/shaders.js.map +1 -0
  854. package/dist/web-driver/tuning.d.ts.map +1 -0
  855. package/dist/web-driver/tuning.js +61 -0
  856. package/dist/web-driver/tuning.js.map +1 -0
  857. package/ios/Kaleidoscope.podspec +22 -15
  858. package/ios/KaleidoscopeModule/BundledImage.swift +39 -0
  859. package/ios/KaleidoscopeModule/CompositeLayers.swift +142 -0
  860. package/ios/KaleidoscopeModule/EffectTuning.swift +86 -86
  861. package/ios/KaleidoscopeModule/KaleidoscopeModule.swift +55 -27
  862. package/ios/KaleidoscopeModule/Registration.swift +36 -57
  863. package/ios/KaleidoscopeModule/effects/CompositeProcessor.swift +906 -0
  864. package/ios/KaleidoscopeModule/effects/FrameBridge.swift +25 -25
  865. package/ios/KaleidoscopeModule/effects/TransformProcessor.swift +127 -126
  866. package/ios/KaleidoscopeModule/gpu/CompositeRendering.swift +352 -0
  867. package/ios/KaleidoscopeModule/gpu/Ingest.swift +104 -102
  868. package/ios/KaleidoscopeModule/gpu/MetalRenderer.swift +473 -544
  869. package/ios/KaleidoscopeModule/gpu/Orientation.swift +41 -41
  870. package/ios/KaleidoscopeModule/gpu/ShaderLibrary.swift +100 -54
  871. package/ios/KaleidoscopeModule/gpu/TextureBridge.swift +245 -244
  872. package/ios/KaleidoscopeModule/segmentation/MaskTuning.swift +11 -11
  873. package/ios/KaleidoscopeModule/segmentation/Segmenter.swift +360 -359
  874. package/ios/KaleidoscopeModule/shaders/GENERATIVE.txt +9 -0
  875. package/ios/KaleidoscopeModule/shaders/SHADERS.txt +13 -2
  876. package/ios/KaleidoscopeModule/shaders/anamorphic-lensflare.metalsrc +47 -0
  877. package/ios/KaleidoscopeModule/shaders/clouds.metalsrc +185 -0
  878. package/ios/KaleidoscopeModule/shaders/composite-blit.metalsrc +22 -0
  879. package/ios/KaleidoscopeModule/shaders/composite-blur.metalsrc +93 -0
  880. package/ios/KaleidoscopeModule/shaders/composite-camera.metalsrc +22 -0
  881. package/ios/KaleidoscopeModule/shaders/composite-image.metalsrc +24 -0
  882. package/ios/KaleidoscopeModule/shaders/composite-masked.metalsrc +22 -0
  883. package/ios/KaleidoscopeModule/shaders/composite-subject.metalsrc +23 -0
  884. package/ios/KaleidoscopeModule/shaders/corporate-blobs.metalsrc +221 -0
  885. package/ios/KaleidoscopeModule/shaders/fireflies.metalsrc +44 -0
  886. package/ios/KaleidoscopeModule/shaders/godrays.metalsrc +46 -0
  887. package/ios/KaleidoscopeModule/shaders/light-beams-and-motes.metalsrc +316 -0
  888. package/ios/KaleidoscopeModule/shaders/nebula.metalsrc +45 -45
  889. package/ios/KaleidoscopeModule/shaders/plasma.metalsrc +26 -0
  890. package/ios/KaleidoscopeModule/shaders/simianlights.metalsrc +45 -45
  891. package/package.json +485 -115
  892. package/plugin/build/android/assets.js +45 -0
  893. package/plugin/build/android/index.js +34 -0
  894. package/plugin/build/index.js +39 -0
  895. package/plugin/build/ios/assets.js +110 -0
  896. package/plugin/build/ios/deployment-target.js +105 -0
  897. package/plugin/build/ios/index.js +63 -0
  898. package/plugin/build/ios/pods.js +73 -0
  899. package/plugin/build/lib/constants.js +15 -0
  900. package/plugin/build/lib/file-manipulation.js +57 -0
  901. package/plugin/build/lib/mods.js +36 -0
  902. package/plugin/build/lib/preset-book.js +215 -0
  903. package/plugin/build/lib/types.js +16 -0
  904. package/src/components/form/control-form.tsx +112 -0
  905. package/src/components/form/make-controls.ts +33 -0
  906. package/src/components/form/scope.ts +9 -0
  907. package/src/components/form/use-field.ts +35 -0
  908. package/src/components/preset-book-menu/index.tsx +286 -0
  909. package/src/components/preset-book-menu/layout.tsx +63 -0
  910. package/src/components/preset-book-menu/preset-book-menu.types.ts +112 -0
  911. package/src/components/preset-book-menu/preset-grid.tsx +80 -0
  912. package/src/components/preset-book-menu/resolve-image-uri.ts +31 -0
  913. package/src/components/preset-book-menu/resolve-image-uri.types.ts +18 -0
  914. package/src/components/preset-book-menu/resolve-image-uri.web.ts +15 -0
  915. package/src/components/preset-control-panel/composite-layer-control-panel.tsx +56 -0
  916. package/src/components/preset-control-panel/control-section.tsx +84 -0
  917. package/src/components/preset-control-panel/control.tsx +50 -0
  918. package/src/components/preset-control-panel/index.ts +31 -0
  919. package/src/components/preset-control-panel/mask-control-panel.tsx +93 -0
  920. package/src/components/preset-control-panel/preset-control-panel.tsx +48 -0
  921. package/src/components/preset-control-panel/transform-control-panel.tsx +146 -0
  922. package/src/components/preset-tile/index.tsx +160 -0
  923. package/src/components/theme/provider.tsx +50 -0
  924. package/src/components/theme/slots.ts +37 -0
  925. package/src/components/ui/button.tsx +54 -0
  926. package/src/components/ui/color-picker.tsx +74 -0
  927. package/src/components/ui/index.ts +10 -0
  928. package/src/components/ui/label.tsx +24 -0
  929. package/src/components/ui/point.tsx +116 -0
  930. package/src/components/ui/polygon-field.tsx +84 -0
  931. package/src/components/ui/readout.tsx +25 -0
  932. package/src/components/ui/slider-value.ts +15 -0
  933. package/src/components/ui/slider.tsx +98 -0
  934. package/src/components/ui/switch.tsx +40 -0
  935. package/src/index.ts +176 -95
  936. package/src/index.web.ts +126 -74
  937. package/src/kaleidoscope/controls.ts +127 -0
  938. package/src/kaleidoscope/effect.ts +5 -0
  939. package/src/kaleidoscope/effect.types.ts +63 -0
  940. package/src/kaleidoscope/shader-to-spec.ts +16 -0
  941. package/src/kaleidoscope/types.ts +101 -0
  942. package/src/kaleidoscope.preset-book.types.ts +105 -0
  943. package/src/lib/primitives.types.ts +5 -0
  944. package/src/lib/test-id.ts +81 -0
  945. package/src/livekit.ts +6 -4
  946. package/src/nativewind.ts +41 -0
  947. package/android/src/main/assets/backgrounds/stylized-dark.webp +0 -0
  948. package/android/src/main/java/com/simiancraft/kaleidoscope/effects/BackgroundImageFactory.kt +0 -365
  949. package/android/src/main/java/com/simiancraft/kaleidoscope/effects/BlurFactory.kt +0 -400
  950. package/dist/backgrounds/dark-office.d.ts +0 -3
  951. package/dist/backgrounds/dark-office.d.ts.map +0 -1
  952. package/dist/backgrounds/dark-office.js +0 -5
  953. package/dist/backgrounds/dark-office.js.map +0 -1
  954. package/dist/backgrounds/dark-office.web.d.ts +0 -3
  955. package/dist/backgrounds/dark-office.web.d.ts.map +0 -1
  956. package/dist/backgrounds/dark-office.web.js +0 -8
  957. package/dist/backgrounds/dark-office.web.js.map +0 -1
  958. package/dist/backgrounds/debug-resolutions.d.ts +0 -3
  959. package/dist/backgrounds/debug-resolutions.d.ts.map +0 -1
  960. package/dist/backgrounds/debug-resolutions.js +0 -6
  961. package/dist/backgrounds/debug-resolutions.js.map +0 -1
  962. package/dist/backgrounds/debug-resolutions.web.d.ts +0 -3
  963. package/dist/backgrounds/debug-resolutions.web.d.ts.map +0 -1
  964. package/dist/backgrounds/debug-resolutions.web.js +0 -8
  965. package/dist/backgrounds/debug-resolutions.web.js.map +0 -1
  966. package/dist/backgrounds/home-dark.d.ts +0 -3
  967. package/dist/backgrounds/home-dark.d.ts.map +0 -1
  968. package/dist/backgrounds/home-dark.js +0 -5
  969. package/dist/backgrounds/home-dark.js.map +0 -1
  970. package/dist/backgrounds/home-dark.web.d.ts +0 -3
  971. package/dist/backgrounds/home-dark.web.d.ts.map +0 -1
  972. package/dist/backgrounds/home-dark.web.js +0 -6
  973. package/dist/backgrounds/home-dark.web.js.map +0 -1
  974. package/dist/backgrounds/home-light.d.ts +0 -3
  975. package/dist/backgrounds/home-light.d.ts.map +0 -1
  976. package/dist/backgrounds/home-light.js +0 -5
  977. package/dist/backgrounds/home-light.js.map +0 -1
  978. package/dist/backgrounds/home-light.web.d.ts +0 -3
  979. package/dist/backgrounds/home-light.web.d.ts.map +0 -1
  980. package/dist/backgrounds/home-light.web.js +0 -6
  981. package/dist/backgrounds/home-light.web.js.map +0 -1
  982. package/dist/backgrounds/index.d.ts +0 -3
  983. package/dist/backgrounds/index.d.ts.map +0 -1
  984. package/dist/backgrounds/index.js +0 -6
  985. package/dist/backgrounds/index.js.map +0 -1
  986. package/dist/backgrounds/light-office.d.ts +0 -3
  987. package/dist/backgrounds/light-office.d.ts.map +0 -1
  988. package/dist/backgrounds/light-office.js +0 -5
  989. package/dist/backgrounds/light-office.js.map +0 -1
  990. package/dist/backgrounds/light-office.web.d.ts +0 -3
  991. package/dist/backgrounds/light-office.web.d.ts.map +0 -1
  992. package/dist/backgrounds/light-office.web.js +0 -8
  993. package/dist/backgrounds/light-office.web.js.map +0 -1
  994. package/dist/backgrounds/nature-dark.d.ts +0 -3
  995. package/dist/backgrounds/nature-dark.d.ts.map +0 -1
  996. package/dist/backgrounds/nature-dark.js +0 -5
  997. package/dist/backgrounds/nature-dark.js.map +0 -1
  998. package/dist/backgrounds/nature-dark.web.d.ts +0 -3
  999. package/dist/backgrounds/nature-dark.web.d.ts.map +0 -1
  1000. package/dist/backgrounds/nature-dark.web.js +0 -6
  1001. package/dist/backgrounds/nature-dark.web.js.map +0 -1
  1002. package/dist/backgrounds/nature-light.d.ts +0 -3
  1003. package/dist/backgrounds/nature-light.d.ts.map +0 -1
  1004. package/dist/backgrounds/nature-light.js +0 -5
  1005. package/dist/backgrounds/nature-light.js.map +0 -1
  1006. package/dist/backgrounds/nature-light.web.d.ts +0 -3
  1007. package/dist/backgrounds/nature-light.web.d.ts.map +0 -1
  1008. package/dist/backgrounds/nature-light.web.js +0 -6
  1009. package/dist/backgrounds/nature-light.web.js.map +0 -1
  1010. package/dist/backgrounds/preset-source.types.d.ts +0 -2
  1011. package/dist/backgrounds/preset-source.types.d.ts.map +0 -1
  1012. package/dist/backgrounds/preset-source.types.js +0 -2
  1013. package/dist/backgrounds/preset-source.types.js.map +0 -1
  1014. package/dist/backgrounds/presets.d.ts +0 -3
  1015. package/dist/backgrounds/presets.d.ts.map +0 -1
  1016. package/dist/backgrounds/presets.js +0 -34
  1017. package/dist/backgrounds/presets.js.map +0 -1
  1018. package/dist/backgrounds/simiancraft-dark.d.ts +0 -3
  1019. package/dist/backgrounds/simiancraft-dark.d.ts.map +0 -1
  1020. package/dist/backgrounds/simiancraft-dark.js +0 -5
  1021. package/dist/backgrounds/simiancraft-dark.js.map +0 -1
  1022. package/dist/backgrounds/simiancraft-dark.web.d.ts +0 -3
  1023. package/dist/backgrounds/simiancraft-dark.web.d.ts.map +0 -1
  1024. package/dist/backgrounds/simiancraft-dark.web.js +0 -6
  1025. package/dist/backgrounds/simiancraft-dark.web.js.map +0 -1
  1026. package/dist/backgrounds/simiancraft-light.d.ts +0 -3
  1027. package/dist/backgrounds/simiancraft-light.d.ts.map +0 -1
  1028. package/dist/backgrounds/simiancraft-light.js +0 -5
  1029. package/dist/backgrounds/simiancraft-light.js.map +0 -1
  1030. package/dist/backgrounds/simiancraft-light.web.d.ts +0 -3
  1031. package/dist/backgrounds/simiancraft-light.web.d.ts.map +0 -1
  1032. package/dist/backgrounds/simiancraft-light.web.js +0 -6
  1033. package/dist/backgrounds/simiancraft-light.web.js.map +0 -1
  1034. package/dist/backgrounds/stylized-dark.d.ts +0 -3
  1035. package/dist/backgrounds/stylized-dark.d.ts.map +0 -1
  1036. package/dist/backgrounds/stylized-dark.js +0 -5
  1037. package/dist/backgrounds/stylized-dark.js.map +0 -1
  1038. package/dist/backgrounds/stylized-dark.web.d.ts +0 -3
  1039. package/dist/backgrounds/stylized-dark.web.d.ts.map +0 -1
  1040. package/dist/backgrounds/stylized-dark.web.js +0 -6
  1041. package/dist/backgrounds/stylized-dark.web.js.map +0 -1
  1042. package/dist/backgrounds/stylized-dark.webp +0 -0
  1043. package/dist/backgrounds/stylized-light.d.ts +0 -3
  1044. package/dist/backgrounds/stylized-light.d.ts.map +0 -1
  1045. package/dist/backgrounds/stylized-light.js +0 -5
  1046. package/dist/backgrounds/stylized-light.js.map +0 -1
  1047. package/dist/backgrounds/stylized-light.web.d.ts +0 -3
  1048. package/dist/backgrounds/stylized-light.web.d.ts.map +0 -1
  1049. package/dist/backgrounds/stylized-light.web.js +0 -6
  1050. package/dist/backgrounds/stylized-light.web.js.map +0 -1
  1051. package/dist/index.d.ts +0 -42
  1052. package/dist/index.d.ts.map +0 -1
  1053. package/dist/index.js +0 -155
  1054. package/dist/index.js.map +0 -1
  1055. package/dist/index.web.d.ts +0 -49
  1056. package/dist/index.web.d.ts.map +0 -1
  1057. package/dist/index.web.js +0 -113
  1058. package/dist/index.web.js.map +0 -1
  1059. package/dist/livekit.d.ts +0 -24
  1060. package/dist/livekit.d.ts.map +0 -1
  1061. package/dist/livekit.js +0 -57
  1062. package/dist/livekit.js.map +0 -1
  1063. package/dist/types.d.ts +0 -74
  1064. package/dist/types.d.ts.map +0 -1
  1065. package/dist/types.js +0 -10
  1066. package/dist/types.js.map +0 -1
  1067. package/dist/web/blur-kernel.d.ts +0 -6
  1068. package/dist/web/blur-kernel.d.ts.map +0 -1
  1069. package/dist/web/blur-kernel.js +0 -41
  1070. package/dist/web/blur-kernel.js.map +0 -1
  1071. package/dist/web/effects/background-image.d.ts +0 -3
  1072. package/dist/web/effects/background-image.d.ts.map +0 -1
  1073. package/dist/web/effects/background-image.js +0 -284
  1074. package/dist/web/effects/background-image.js.map +0 -1
  1075. package/dist/web/effects/blur.d.ts +0 -3
  1076. package/dist/web/effects/blur.d.ts.map +0 -1
  1077. package/dist/web/effects/blur.js +0 -339
  1078. package/dist/web/effects/blur.js.map +0 -1
  1079. package/dist/web/effects/transform.d.ts +0 -4
  1080. package/dist/web/effects/transform.d.ts.map +0 -1
  1081. package/dist/web/effects/transform.js +0 -62
  1082. package/dist/web/effects/transform.js.map +0 -1
  1083. package/dist/web/insertable-streams.d.ts.map +0 -1
  1084. package/dist/web/insertable-streams.js +0 -64
  1085. package/dist/web/insertable-streams.js.map +0 -1
  1086. package/dist/web/segmenter.d.ts.map +0 -1
  1087. package/dist/web/segmenter.js +0 -83
  1088. package/dist/web/segmenter.js.map +0 -1
  1089. package/dist/web/shaders.d.ts +0 -2
  1090. package/dist/web/shaders.d.ts.map +0 -1
  1091. package/dist/web/shaders.generated.d.ts +0 -4
  1092. package/dist/web/shaders.generated.d.ts.map +0 -1
  1093. package/dist/web/shaders.generated.js +0 -54
  1094. package/dist/web/shaders.generated.js.map +0 -1
  1095. package/dist/web/shaders.js +0 -32
  1096. package/dist/web/shaders.js.map +0 -1
  1097. package/dist/web/tuning.d.ts.map +0 -1
  1098. package/dist/web/tuning.js +0 -55
  1099. package/dist/web/tuning.js.map +0 -1
  1100. package/ios/KaleidoscopeModule/effects/BackgroundImageProcessor.swift +0 -293
  1101. package/ios/KaleidoscopeModule/effects/BlurProcessor.swift +0 -238
  1102. package/ios/KaleidoscopeModule/resources/backgrounds/dark-office.webp +0 -0
  1103. package/ios/KaleidoscopeModule/resources/backgrounds/debug-resolutions.webp +0 -0
  1104. package/ios/KaleidoscopeModule/resources/backgrounds/home-dark.webp +0 -0
  1105. package/ios/KaleidoscopeModule/resources/backgrounds/home-light.webp +0 -0
  1106. package/ios/KaleidoscopeModule/resources/backgrounds/light-office.webp +0 -0
  1107. package/ios/KaleidoscopeModule/resources/backgrounds/nature-dark.webp +0 -0
  1108. package/ios/KaleidoscopeModule/resources/backgrounds/nature-light.webp +0 -0
  1109. package/ios/KaleidoscopeModule/resources/backgrounds/simiancraft-dark.webp +0 -0
  1110. package/ios/KaleidoscopeModule/resources/backgrounds/simiancraft-light.webp +0 -0
  1111. package/ios/KaleidoscopeModule/resources/backgrounds/stylized-dark.webp +0 -0
  1112. package/ios/KaleidoscopeModule/resources/backgrounds/stylized-light.webp +0 -0
  1113. package/ios/KaleidoscopeModule/shaders/blur.metalsrc +0 -72
  1114. package/ios/KaleidoscopeModule/shaders/composite.metalsrc +0 -22
  1115. package/src/backgrounds/README.md +0 -83
  1116. package/src/backgrounds/dark-office.ts +0 -6
  1117. package/src/backgrounds/dark-office.web.ts +0 -9
  1118. package/src/backgrounds/dark-office.webp +0 -0
  1119. package/src/backgrounds/debug-resolutions.ts +0 -7
  1120. package/src/backgrounds/debug-resolutions.web.ts +0 -9
  1121. package/src/backgrounds/debug-resolutions.webp +0 -0
  1122. package/src/backgrounds/home-dark.ts +0 -6
  1123. package/src/backgrounds/home-dark.web.ts +0 -7
  1124. package/src/backgrounds/home-dark.webp +0 -0
  1125. package/src/backgrounds/home-light.ts +0 -6
  1126. package/src/backgrounds/home-light.web.ts +0 -7
  1127. package/src/backgrounds/home-light.webp +0 -0
  1128. package/src/backgrounds/index.ts +0 -7
  1129. package/src/backgrounds/light-office.ts +0 -6
  1130. package/src/backgrounds/light-office.web.ts +0 -9
  1131. package/src/backgrounds/light-office.webp +0 -0
  1132. package/src/backgrounds/nature-dark.ts +0 -6
  1133. package/src/backgrounds/nature-dark.web.ts +0 -7
  1134. package/src/backgrounds/nature-dark.webp +0 -0
  1135. package/src/backgrounds/nature-light.ts +0 -6
  1136. package/src/backgrounds/nature-light.web.ts +0 -7
  1137. package/src/backgrounds/nature-light.webp +0 -0
  1138. package/src/backgrounds/preset-source.types.ts +0 -5
  1139. package/src/backgrounds/presets.ts +0 -36
  1140. package/src/backgrounds/simiancraft-dark.ts +0 -6
  1141. package/src/backgrounds/simiancraft-dark.web.ts +0 -7
  1142. package/src/backgrounds/simiancraft-dark.webp +0 -0
  1143. package/src/backgrounds/simiancraft-light.ts +0 -6
  1144. package/src/backgrounds/simiancraft-light.web.ts +0 -7
  1145. package/src/backgrounds/simiancraft-light.webp +0 -0
  1146. package/src/backgrounds/stylized-dark.ts +0 -6
  1147. package/src/backgrounds/stylized-dark.web.ts +0 -7
  1148. package/src/backgrounds/stylized-dark.webp +0 -0
  1149. package/src/backgrounds/stylized-light.ts +0 -6
  1150. package/src/backgrounds/stylized-light.web.ts +0 -7
  1151. package/src/backgrounds/stylized-light.webp +0 -0
  1152. package/src/types.ts +0 -89
  1153. package/src/web/blur-kernel.ts +0 -44
  1154. package/src/web/effects/background-image.ts +0 -364
  1155. package/src/web/effects/blur.ts +0 -430
  1156. package/src/web/effects/transform.ts +0 -69
  1157. package/src/web/insertable-streams.ts +0 -112
  1158. package/src/web/segmenter.ts +0 -107
  1159. package/src/web/shaders.generated.ts +0 -56
  1160. package/src/web/shaders.ts +0 -31
  1161. package/src/web/tuning.ts +0 -67
  1162. /package/{src/backgrounds → catalog/images}/assets.d.ts +0 -0
  1163. /package/{android/src/main/assets/backgrounds → catalog/images/debug}/debug-resolutions.webp +0 -0
  1164. /package/{android/src/main/assets/backgrounds → catalog/images/home}/home-dark.webp +0 -0
  1165. /package/{android/src/main/assets/backgrounds → catalog/images/home}/home-light.webp +0 -0
  1166. /package/{android/src/main/assets/backgrounds/nature-dark.webp → catalog/images/nature/landscape-dark.webp} +0 -0
  1167. /package/{android/src/main/assets/backgrounds/nature-light.webp → catalog/images/nature/landscape-light.webp} +0 -0
  1168. /package/{android/src/main/assets/backgrounds/dark-office.webp → catalog/images/office/office-dark.webp} +0 -0
  1169. /package/{android/src/main/assets/backgrounds/light-office.webp → catalog/images/office/office-light.webp} +0 -0
  1170. /package/{android/src/main/assets/backgrounds/stylized-light.webp → catalog/images/sci-fi/sci-fi-light.webp} +0 -0
  1171. /package/{android/src/main/assets/backgrounds → catalog/images/simiancraft}/simiancraft-dark.webp +0 -0
  1172. /package/{android/src/main/assets/backgrounds → catalog/images/simiancraft}/simiancraft-light.webp +0 -0
  1173. /package/dist/{backgrounds → catalog/images/debug}/debug-resolutions.webp +0 -0
  1174. /package/dist/{backgrounds → catalog/images/home}/home-dark.webp +0 -0
  1175. /package/dist/{backgrounds → catalog/images/home}/home-light.webp +0 -0
  1176. /package/dist/{backgrounds/nature-dark.webp → catalog/images/nature/landscape-dark.webp} +0 -0
  1177. /package/dist/{backgrounds/nature-light.webp → catalog/images/nature/landscape-light.webp} +0 -0
  1178. /package/dist/{backgrounds/dark-office.webp → catalog/images/office/office-dark.webp} +0 -0
  1179. /package/dist/{backgrounds/light-office.webp → catalog/images/office/office-light.webp} +0 -0
  1180. /package/dist/{backgrounds/stylized-light.webp → catalog/images/sci-fi/sci-fi-light.webp} +0 -0
  1181. /package/dist/{backgrounds → catalog/images/simiancraft}/simiancraft-dark.webp +0 -0
  1182. /package/dist/{backgrounds → catalog/images/simiancraft}/simiancraft-light.webp +0 -0
  1183. /package/dist/{web → web-driver}/insertable-streams.d.ts +0 -0
  1184. /package/dist/{web → web-driver}/segmenter.d.ts +0 -0
  1185. /package/dist/{web → web-driver}/tuning.d.ts +0 -0
@@ -1,11 +1,12 @@
1
1
  // Shared Metal renderer for the iOS Kaleidoscope effects. Owns the
2
2
  // MTLDevice, command queue, the CVMetalTextureCache used for both input
3
3
  // ingestion and output, the precompiled-at-runtime pipeline states for the
4
- // three transpiled shaders (passthrough, blur, composite), an output
5
- // CVPixelBufferPool, and the blur ping-pong intermediate textures.
4
+ // passthrough vertex and the transform fragment, and an output
5
+ // CVPixelBufferPool. The per-layer composite fragments and the generative
6
+ // shaders compile lazily in CompositeProcessor.
6
7
  //
7
- // One instance is created per processor (BlurProcessor, BackgroundImage-
8
- // Processor); a processor's `capturer:didCaptureVideoFrame:` is the only
8
+ // One instance is created per processor (CompositeProcessor, TransformProcessor);
9
+ // a processor's `capturer:didCaptureVideoFrame:` is the only
9
10
  // caller, and the upstream rn-webrtc pipeline serializes per processor on a
10
11
  // single capture queue, so the renderer does not need its own lock. The
11
12
  // owning processor still wraps every call in its own try/catch and falls
@@ -30,572 +31,500 @@
30
31
  // cannot introduce a vertical flip. This is the verification anchor for the
31
32
  // whole convention.
32
33
 
34
+ import CoreVideo
33
35
  import Foundation
34
36
  import Metal
35
- import CoreVideo
36
- import simd
37
37
  import os.log
38
+ import simd
38
39
 
39
40
  /// Errors thrown during renderer setup or per-frame work. The owning
40
41
  /// processor catches these and falls through to the original frame.
41
42
  enum RendererError: Error {
42
- case noMetalDevice
43
- case libraryCompileFailed(String)
44
- case missingFunction(String)
45
- case pipelineCreateFailed(String)
46
- case textureCacheCreateFailed(OSStatus)
47
- case pixelBufferPoolCreateFailed(OSStatus)
48
- case pixelBufferAllocFailed(OSStatus)
49
- case textureBindFailed(String)
50
- case commandBufferUnavailable
43
+ case noMetalDevice
44
+ case libraryCompileFailed(String)
45
+ case missingFunction(String)
46
+ case pipelineCreateFailed(String)
47
+ case textureCacheCreateFailed(OSStatus)
48
+ case pixelBufferPoolCreateFailed(OSStatus)
49
+ case pixelBufferAllocFailed(OSStatus)
50
+ case textureBindFailed(String)
51
+ case commandBufferUnavailable
51
52
  }
52
53
 
53
54
  final class MetalRenderer {
54
- static let log = OSLog(subsystem: "com.simiancraft.kaleidoscope", category: "Renderer")
55
- static let perfLog = OSLog(subsystem: "com.simiancraft.kaleidoscope", category: "Perf")
56
-
57
- let device: MTLDevice
58
- private let commandQueue: MTLCommandQueue
59
- let textureCache: CVMetalTextureCache
60
-
61
- // R3 frame-pipelining. Instead of committing the current command buffer and
62
- // blocking on waitUntilCompleted (which serializes CPU and GPU every frame),
63
- // we commit asynchronously and return the PREVIOUS frame's completed output,
64
- // adding one frame of latency. The semaphore caps the number of command
65
- // buffers in flight so the CPU cannot outrun the GPU unboundedly; value 2
66
- // lets the GPU work on frame N while the CPU encodes frame N+1. The output
67
- // CVPixelBufferPool (min 3) has enough buffers to back the in-flight frame,
68
- // the held previous frame, and one being dequeued.
69
- private let inFlightSemaphore = DispatchSemaphore(value: 2)
70
-
71
- // The most recent output buffer whose GPU work has COMPLETED, published by
72
- // the command-buffer completion handler. The capture thread reads it to
73
- // return last frame's result while this frame's work runs asynchronously.
74
- // nil before the first frame completes; the caller forwards the original
75
- // frame in that case. Publishing only on completion (rather than relying on
76
- // the semaphore + in-order queue to imply completion) means a returned buffer
77
- // is never read by WebRTC before the GPU finished writing it: the buffer-
78
- // lifecycle safety is explicit, not timing-derived. Shared between the
79
- // completion handler (writer) and the capture thread (reader); guarded by
80
- // pipelineLock.
81
- private var readyOutput: CVPixelBuffer?
82
- private var pipelineLock = os_unfair_lock_s()
83
-
84
- // Pipeline states for the three transpiled shaders. All three .metal files
85
- // share the entry-point name `main0` (spirv-cross emits that for every
86
- // stage), so they CANNOT coexist in one MTLLibrary. Each is compiled into
87
- // its OWN MTLLibrary at runtime from the .metal source text read out of the
88
- // Kaleidoscope resource bundle, and we pull `main0` from each. See
89
- // ShaderLibrary.swift for the loader. Runtime makeLibrary(source:) is the
90
- // safe path here because renaming the entry points would be clobbered the
91
- // next time scripts/transpile-shaders.ts regenerates the MSL.
92
- let passthroughVertex: MTLFunction
93
- let blurPipeline: MTLRenderPipelineState
94
- let compositePipeline: MTLRenderPipelineState
95
- let transformPipeline: MTLRenderPipelineState
96
-
97
- // Linear-clamp sampler shared by every pass (matches the Android GL_LINEAR
98
- // + GL_CLAMP_TO_EDGE setup). Clamp avoids edge bleed when cover-fit UVs or
99
- // blur taps reach outside [0,1].
100
- let linearClampSampler: MTLSamplerState
101
-
102
- // Output pool + cached dimensions. Recreated on resolution change.
103
- private var outputPool: CVPixelBufferPool?
104
- private var poolWidth = 0
105
- private var poolHeight = 0
106
-
107
- // Blur ping-pong intermediate textures (BGRA, full input resolution).
108
- // Recreated on resolution change. Only allocated when the blur path runs.
109
- private var blurTexA: MTLTexture?
110
- private var blurTexB: MTLTexture?
111
- private var blurTexWidth = 0
112
- private var blurTexHeight = 0
113
-
114
- // "original" RGB ingest buffers come from a POOL, not a single reused buffer.
115
- // CoreImage renders each frame's NV12 input into a freshly dequeued buffer
116
- // (TextureBridge.ingest) and the GPU passes sample a per-frame texture view of
117
- // it. A single shared buffer is WRONG here: under R3 frame-pipelining the
118
- // previous frame's command buffer is still reading the original after
119
- // process() returns, AND the segmenter's async worker still reads it (it
120
- // retains the ref for its downscale), so overwriting one buffer in place
121
- // corrupted those in-flight reads (the mask drift / "fog of war"). A pool only
122
- // recycles a buffer once every reader has released it: the command buffer via
123
- // commitPipelined's keepAlive, the segmenter via its async closure's retain.
124
- private var originalPool: CVPixelBufferPool?
125
- private var originalPoolWidth = 0
126
- private var originalPoolHeight = 0
127
-
128
- init(bundle: Bundle) throws {
129
- guard let dev = MTLCreateSystemDefaultDevice() else {
130
- throw RendererError.noMetalDevice
55
+ static let log = OSLog(subsystem: "com.simiancraft.kaleidoscope", category: "Renderer")
56
+ static let perfLog = OSLog(subsystem: "com.simiancraft.kaleidoscope", category: "Perf")
57
+
58
+ let device: MTLDevice
59
+ private let commandQueue: MTLCommandQueue
60
+ let textureCache: CVMetalTextureCache
61
+
62
+ /// R3 frame-pipelining. Instead of committing the current command buffer and
63
+ /// blocking on waitUntilCompleted (which serializes CPU and GPU every frame),
64
+ /// we commit asynchronously and return the PREVIOUS frame's completed output,
65
+ /// adding one frame of latency. The semaphore caps the number of command
66
+ /// buffers in flight so the CPU cannot outrun the GPU unboundedly; value 2
67
+ /// lets the GPU work on frame N while the CPU encodes frame N+1. The output
68
+ /// CVPixelBufferPool (min 3) has enough buffers to back the in-flight frame,
69
+ /// the held previous frame, and one being dequeued.
70
+ private let inFlightSemaphore = DispatchSemaphore(value: 2)
71
+
72
+ // The most recent output buffer whose GPU work has COMPLETED, published by
73
+ // the command-buffer completion handler. The capture thread reads it to
74
+ // return last frame's result while this frame's work runs asynchronously.
75
+ // nil before the first frame completes; the caller forwards the original
76
+ // frame in that case. Publishing only on completion (rather than relying on
77
+ // the semaphore + in-order queue to imply completion) means a returned buffer
78
+ // is never read by WebRTC before the GPU finished writing it: the buffer-
79
+ // lifecycle safety is explicit, not timing-derived. Shared between the
80
+ // completion handler (writer) and the capture thread (reader); guarded by
81
+ // pipelineLock.
82
+ private var readyOutput: CVPixelBuffer?
83
+ private var pipelineLock = os_unfair_lock_s()
84
+
85
+ // Pipeline states for the three transpiled shaders. All three .metal files
86
+ // share the entry-point name `main0` (spirv-cross emits that for every
87
+ // stage), so they CANNOT coexist in one MTLLibrary. Each is compiled into
88
+ // its OWN MTLLibrary at runtime from the .metal source text read out of the
89
+ // Kaleidoscope resource bundle, and we pull `main0` from each. See
90
+ // ShaderLibrary.swift for the loader. Runtime makeLibrary(source:) is the
91
+ // safe path here because renaming the entry points would be clobbered the
92
+ // next time scripts/transpile-shaders.ts regenerates the MSL.
93
+ let passthroughVertex: MTLFunction
94
+ let transformPipeline: MTLRenderPipelineState
95
+
96
+ /// Linear-clamp sampler shared by every pass (matches the Android GL_LINEAR
97
+ /// + GL_CLAMP_TO_EDGE setup). Clamp avoids edge bleed when cover-fit UVs or
98
+ /// blur taps reach outside [0,1].
99
+ let linearClampSampler: MTLSamplerState
100
+
101
+ // Output pool + cached dimensions. Recreated on resolution change.
102
+ private var outputPool: CVPixelBufferPool?
103
+ private var poolWidth = 0
104
+ private var poolHeight = 0
105
+
106
+ // Composite compositor scratch render targets (BGRA, full output resolution).
107
+ // scratchA holds a subject layer's rendered content and the blur's horizontal
108
+ // pass; scratchB holds the blur's vertical pass. Recreated on resolution
109
+ // change; allocated only when the composite compositor's scratch path runs. Used
110
+ // via the CompositeRendering extension's compositeScratch(width:height:); kept
111
+ // distinct from the standalone blur ping-pong above so the two paths never
112
+ // alias. `internal` (not private) so the extension in CompositeRendering.swift
113
+ // can reach them; a Swift extension cannot add stored properties, so they live
114
+ // on the class here.
115
+ var compositeScratchA: MTLTexture?
116
+ var compositeScratchB: MTLTexture?
117
+ var compositeScratchWidth = 0
118
+ var compositeScratchHeight = 0
119
+
120
+ // "original" RGB ingest buffers come from a POOL, not a single reused buffer.
121
+ // CoreImage renders each frame's NV12 input into a freshly dequeued buffer
122
+ // (TextureBridge.ingest) and the GPU passes sample a per-frame texture view of
123
+ // it. A single shared buffer is WRONG here: under R3 frame-pipelining the
124
+ // previous frame's command buffer is still reading the original after
125
+ // process() returns, AND the segmenter's async worker still reads it (it
126
+ // retains the ref for its downscale), so overwriting one buffer in place
127
+ // corrupted those in-flight reads (the mask drift / "fog of war"). A pool only
128
+ // recycles a buffer once every reader has released it: the command buffer via
129
+ // commitPipelined's keepAlive, the segmenter via its async closure's retain.
130
+ private var originalPool: CVPixelBufferPool?
131
+ private var originalPoolWidth = 0
132
+ private var originalPoolHeight = 0
133
+
134
+ init(bundle: Bundle) throws {
135
+ guard let dev = MTLCreateSystemDefaultDevice() else {
136
+ throw RendererError.noMetalDevice
137
+ }
138
+ device = dev
139
+
140
+ guard let queue = dev.makeCommandQueue() else {
141
+ throw RendererError.pipelineCreateFailed("makeCommandQueue returned nil")
142
+ }
143
+ commandQueue = queue
144
+
145
+ var cache: CVMetalTextureCache?
146
+ let cacheStatus = CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, dev, nil, &cache)
147
+ guard cacheStatus == kCVReturnSuccess, let unwrappedCache = cache else {
148
+ throw RendererError.textureCacheCreateFailed(cacheStatus)
149
+ }
150
+ textureCache = unwrappedCache
151
+
152
+ // Compile each .metal as its own library and pull `main0`.
153
+ let passthrough = try ShaderLibrary(device: dev, bundle: bundle, fileName: "passthrough")
154
+ let transform = try ShaderLibrary(device: dev, bundle: bundle, fileName: "transform")
155
+
156
+ passthroughVertex = try passthrough.function()
157
+
158
+ // The transform fragment pipeline reuses the passthrough vertex (fullscreen
159
+ // quad generated from gl_VertexID via TRIANGLE_STRIP; no vertex buffer).
160
+ // The shader is designed for FOUR vertices (see shaders/passthrough.vert);
161
+ // see drawFullscreen below for the matching drawPrimitives call. The
162
+ // per-layer composite fragments and the composite blur compile lazily in
163
+ // CompositeProcessor; the generative fragments via makeGenerativePipeline.
164
+ transformPipeline = try MetalRenderer.makePipeline(
165
+ device: dev,
166
+ vertex: passthroughVertex,
167
+ fragment: transform.function(),
168
+ label: "transform"
169
+ )
170
+
171
+ let samplerDesc = MTLSamplerDescriptor()
172
+ samplerDesc.minFilter = .linear
173
+ samplerDesc.magFilter = .linear
174
+ samplerDesc.sAddressMode = .clampToEdge
175
+ samplerDesc.tAddressMode = .clampToEdge
176
+ guard let sampler = dev.makeSamplerState(descriptor: samplerDesc) else {
177
+ throw RendererError.pipelineCreateFailed("makeSamplerState returned nil")
178
+ }
179
+ linearClampSampler = sampler
131
180
  }
132
- self.device = dev
133
181
 
134
- guard let queue = dev.makeCommandQueue() else {
135
- throw RendererError.pipelineCreateFailed("makeCommandQueue returned nil")
182
+ private static func makePipeline(
183
+ device: MTLDevice,
184
+ vertex: MTLFunction,
185
+ fragment: MTLFunction,
186
+ label: String
187
+ ) throws -> MTLRenderPipelineState {
188
+ let desc = MTLRenderPipelineDescriptor()
189
+ desc.label = label
190
+ desc.vertexFunction = vertex
191
+ desc.fragmentFunction = fragment
192
+ // All passes render into BGRA buffers (intermediates and the output).
193
+ desc.colorAttachments[0].pixelFormat = .bgra8Unorm
194
+ do {
195
+ return try device.makeRenderPipelineState(descriptor: desc)
196
+ } catch {
197
+ throw RendererError.pipelineCreateFailed("\(label): \(error.localizedDescription)")
198
+ }
136
199
  }
137
- self.commandQueue = queue
138
200
 
139
- var cache: CVMetalTextureCache?
140
- let cacheStatus = CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, dev, nil, &cache)
141
- guard cacheStatus == kCVReturnSuccess, let unwrappedCache = cache else {
142
- throw RendererError.textureCacheCreateFailed(cacheStatus)
143
- }
144
- self.textureCache = unwrappedCache
145
-
146
- // Compile each .metal as its own library and pull `main0`.
147
- let passthrough = try ShaderLibrary(device: dev, bundle: bundle, fileName: "passthrough")
148
- let blur = try ShaderLibrary(device: dev, bundle: bundle, fileName: "blur")
149
- let composite = try ShaderLibrary(device: dev, bundle: bundle, fileName: "composite")
150
- let transform = try ShaderLibrary(device: dev, bundle: bundle, fileName: "transform")
151
-
152
- self.passthroughVertex = try passthrough.function()
153
-
154
- // Both fragment pipelines reuse the passthrough vertex (fullscreen
155
- // quad generated from gl_VertexID via TRIANGLE_STRIP; no vertex buffer).
156
- // The shader is designed for FOUR vertices (see shaders/passthrough.vert);
157
- // see drawFullscreen below for the matching drawPrimitives call.
158
- self.blurPipeline = try MetalRenderer.makePipeline(
159
- device: dev,
160
- vertex: passthroughVertex,
161
- fragment: try blur.function(),
162
- label: "blur"
163
- )
164
- self.compositePipeline = try MetalRenderer.makePipeline(
165
- device: dev,
166
- vertex: passthroughVertex,
167
- fragment: try composite.function(),
168
- label: "composite"
169
- )
170
- self.transformPipeline = try MetalRenderer.makePipeline(
171
- device: dev,
172
- vertex: passthroughVertex,
173
- fragment: try transform.function(),
174
- label: "transform"
175
- )
176
-
177
- let samplerDesc = MTLSamplerDescriptor()
178
- samplerDesc.minFilter = .linear
179
- samplerDesc.magFilter = .linear
180
- samplerDesc.sAddressMode = .clampToEdge
181
- samplerDesc.tAddressMode = .clampToEdge
182
- guard let sampler = dev.makeSamplerState(descriptor: samplerDesc) else {
183
- throw RendererError.pipelineCreateFailed("makeSamplerState returned nil")
184
- }
185
- self.linearClampSampler = sampler
186
- }
187
-
188
- private static func makePipeline(
189
- device: MTLDevice,
190
- vertex: MTLFunction,
191
- fragment: MTLFunction,
192
- label: String
193
- ) throws -> MTLRenderPipelineState {
194
- let desc = MTLRenderPipelineDescriptor()
195
- desc.label = label
196
- desc.vertexFunction = vertex
197
- desc.fragmentFunction = fragment
198
- // All passes render into BGRA buffers (intermediates and the output).
199
- desc.colorAttachments[0].pixelFormat = .bgra8Unorm
200
- do {
201
- return try device.makeRenderPipelineState(descriptor: desc)
202
- } catch {
203
- throw RendererError.pipelineCreateFailed("\(label): \(error.localizedDescription)")
201
+ func makeCommandBuffer() throws -> MTLCommandBuffer {
202
+ guard let cb = commandQueue.makeCommandBuffer() else {
203
+ throw RendererError.commandBufferUnavailable
204
+ }
205
+ return cb
204
206
  }
205
- }
206
207
 
207
- func makeCommandBuffer() throws -> MTLCommandBuffer {
208
- guard let cb = commandQueue.makeCommandBuffer() else {
209
- throw RendererError.commandBufferUnavailable
210
- }
211
- return cb
212
- }
213
-
214
- /// R3 frame-pipelining commit. Replaces `commit()` + `waitUntilCompleted()`.
215
- ///
216
- /// - Throttles in-flight command buffers via the semaphore (waits before
217
- /// commit; the completion handler signals), so the CPU cannot outrun the
218
- /// GPU unboundedly. The literal R3 sketch waits "before encoding"; we wait
219
- /// here, immediately before commit, which bounds the GPU-relevant quantity
220
- /// (committed-but-incomplete buffers) identically and keeps the throttle in
221
- /// one place. The processor's per-frame work between makeCommandBuffer and
222
- /// this call is cheap CPU encoding, not GPU execution.
223
- /// - Registers a completion handler that PUBLISHES `currentOutput` as the
224
- /// ready-to-return buffer only once the GPU has finished writing it, then
225
- /// signals the semaphore. Optionally logs GPU time under "Perf".
226
- /// - Commits asynchronously (no wait) and returns the PREVIOUSLY-published
227
- /// output, i.e. last frame's completed result. Returns nil before any frame
228
- /// has completed (first frame); the caller forwards the original frame.
229
- ///
230
- /// `currentOutput` must be the pooled buffer the command buffer wrote into
231
- /// this frame. The returned buffer (last frame's) is a distinct pooled buffer;
232
- /// the pool's min count keeps current, previously-returned, and in-flight
233
- /// buffers from colliding.
234
- ///
235
- /// `keepAlive` holds any per-frame references whose backing the GPU reads or
236
- /// writes for this command buffer but which would otherwise be released when
237
- /// the encoding frame returns: the input/mask CVPixelBuffers AND the
238
- /// CVMetalTexture wrappers vended by TextureBridge.makeTexture (the wrapper, not
239
- /// the bare MTLTexture, is what pins the IOSurface for the cache). Under R3 the
240
- /// command buffer is still in flight after process() returns, so capturing these
241
- /// in the completion handler keeps them live for exactly as long as the GPU
242
- /// needs them and no longer; without this the source pool can reclaim and
243
- /// overwrite a buffer mid-GPU-read (the segmentation-mask curl-noise drift).
244
- func commitPipelined(
245
- _ commandBuffer: MTLCommandBuffer,
246
- currentOutput: CVPixelBuffer,
247
- keepAlive: [Any],
248
- debugTiming: Bool,
249
- timingLabel: String
250
- ) -> CVPixelBuffer? {
251
- inFlightSemaphore.wait()
252
- commandBuffer.addCompletedHandler { [weak self] completed in
253
- // Hold the per-frame inputs/wrappers until the GPU finishes. Referencing
254
- // `keepAlive` inside the closure is the entire point: it extends their
255
- // lifetime to command-buffer completion. Touched but intentionally unused.
256
- _ = keepAlive
257
- guard let self = self else { return }
258
- if debugTiming {
259
- let gpuMs = (completed.gpuEndTime - completed.gpuStartTime) * 1000.0
260
- os_log("%{public}@ gpu: %.2f ms", log: MetalRenderer.perfLog, type: .info,
261
- timingLabel, gpuMs)
262
- }
263
- if completed.error == nil {
264
- os_unfair_lock_lock(&self.pipelineLock)
265
- self.readyOutput = currentOutput
266
- os_unfair_lock_unlock(&self.pipelineLock)
267
- } else {
268
- os_log("%{public}@ command buffer error: %{public}@",
269
- log: MetalRenderer.log, type: .error,
270
- timingLabel, completed.error?.localizedDescription ?? "unknown")
271
- }
272
- self.inFlightSemaphore.signal()
273
- }
274
- commandBuffer.commit()
275
-
276
- os_unfair_lock_lock(&pipelineLock)
277
- let previous = readyOutput
278
- os_unfair_lock_unlock(&pipelineLock)
279
- return previous
280
- }
281
-
282
- // MARK: - Output buffer pool
283
-
284
- /// Returns a fresh BGRA, IOSurface-backed, Metal-compatible CVPixelBuffer
285
- /// from the pool, recreating the pool if dimensions changed. The pool keeps
286
- /// allocation off the per-frame hot path; the buffer is owned by the caller
287
- /// and released when the RTCVideoFrame that wraps it is released.
288
- func dequeueOutputBuffer(width: Int, height: Int) throws -> CVPixelBuffer {
289
- if outputPool == nil || poolWidth != width || poolHeight != height {
290
- try rebuildOutputPool(width: width, height: height)
291
- }
292
- guard let pool = outputPool else {
293
- throw RendererError.pixelBufferPoolCreateFailed(kCVReturnError)
294
- }
295
- var pixelBuffer: CVPixelBuffer?
296
- let status = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pool, &pixelBuffer)
297
- guard status == kCVReturnSuccess, let buffer = pixelBuffer else {
298
- throw RendererError.pixelBufferAllocFailed(status)
299
- }
300
- return buffer
301
- }
302
-
303
- private func rebuildOutputPool(width: Int, height: Int) throws {
304
- // min 4 covers the worst-case live set now that the completion handler
305
- // retains `currentOutput` until the GPU finishes: the semaphore (value 2)
306
- // permits TWO command buffers in flight, so two distinct `currentOutput`
307
- // buffers can be captured at once, PLUS the previously-published
308
- // `readyOutput` the capture thread may still be handing to WebRTC, PLUS the
309
- // one being dequeued this frame. 2 + 1 + 1 = 4. The pool grows past the
310
- // minimum if all are momentarily live, so 4 is the steady-state floor, not a
311
- // hard cap.
312
- outputPool = try MetalRenderer.makeBGRAMetalPool(width: width, height: height, minCount: 4)
313
- poolWidth = width
314
- poolHeight = height
315
- }
316
-
317
- /// Creates a CVPixelBufferPool of BGRA, IOSurface-backed, Metal-compatible
318
- /// buffers. Shared by the output pool and the original-ingest pool. IOSurface-
319
- /// backed so downstream (RTCCVPixelBuffer -> I420 -> encoder) accepts the
320
- /// buffer; Metal-compatible so CVMetalTextureCache can wrap it as a texture
321
- /// without a copy. Pools grow past `minCount` if more buffers are momentarily
322
- /// live, so the count is a steady-state floor, not a hard cap.
323
- private static func makeBGRAMetalPool(width: Int, height: Int, minCount: Int) throws
324
- -> CVPixelBufferPool {
325
- let pixelBufferAttributes: [String: Any] = [
326
- kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA,
327
- kCVPixelBufferWidthKey as String: width,
328
- kCVPixelBufferHeightKey as String: height,
329
- kCVPixelBufferIOSurfacePropertiesKey as String: [String: Any](),
330
- kCVPixelBufferMetalCompatibilityKey as String: true,
331
- ]
332
- let poolAttributes: [String: Any] = [
333
- kCVPixelBufferPoolMinimumBufferCountKey as String: minCount,
334
- ]
335
- var pool: CVPixelBufferPool?
336
- let status = CVPixelBufferPoolCreate(
337
- kCFAllocatorDefault,
338
- poolAttributes as CFDictionary,
339
- pixelBufferAttributes as CFDictionary,
340
- &pool
341
- )
342
- guard status == kCVReturnSuccess, let createdPool = pool else {
343
- throw RendererError.pixelBufferPoolCreateFailed(status)
208
+ /// R3 frame-pipelining commit. Replaces `commit()` + `waitUntilCompleted()`.
209
+ ///
210
+ /// - Throttles in-flight command buffers via the semaphore (waits before
211
+ /// commit; the completion handler signals), so the CPU cannot outrun the
212
+ /// GPU unboundedly. The literal R3 sketch waits "before encoding"; we wait
213
+ /// here, immediately before commit, which bounds the GPU-relevant quantity
214
+ /// (committed-but-incomplete buffers) identically and keeps the throttle in
215
+ /// one place. The processor's per-frame work between makeCommandBuffer and
216
+ /// this call is cheap CPU encoding, not GPU execution.
217
+ /// - Registers a completion handler that PUBLISHES `currentOutput` as the
218
+ /// ready-to-return buffer only once the GPU has finished writing it, then
219
+ /// signals the semaphore. Optionally logs GPU time under "Perf".
220
+ /// - Commits asynchronously (no wait) and returns the PREVIOUSLY-published
221
+ /// output, i.e. last frame's completed result. Returns nil before any frame
222
+ /// has completed (first frame); the caller forwards the original frame.
223
+ ///
224
+ /// `currentOutput` must be the pooled buffer the command buffer wrote into
225
+ /// this frame. The returned buffer (last frame's) is a distinct pooled buffer;
226
+ /// the pool's min count keeps current, previously-returned, and in-flight
227
+ /// buffers from colliding.
228
+ ///
229
+ /// `keepAlive` holds any per-frame references whose backing the GPU reads or
230
+ /// writes for this command buffer but which would otherwise be released when
231
+ /// the encoding frame returns: the input/mask CVPixelBuffers AND the
232
+ /// CVMetalTexture wrappers vended by TextureBridge.makeTexture (the wrapper, not
233
+ /// the bare MTLTexture, is what pins the IOSurface for the cache). Under R3 the
234
+ /// command buffer is still in flight after process() returns, so capturing these
235
+ /// in the completion handler keeps them live for exactly as long as the GPU
236
+ /// needs them and no longer; without this the source pool can reclaim and
237
+ /// overwrite a buffer mid-GPU-read (the segmentation-mask curl-noise drift).
238
+ func commitPipelined(
239
+ _ commandBuffer: MTLCommandBuffer,
240
+ currentOutput: CVPixelBuffer,
241
+ keepAlive: [Any],
242
+ debugTiming: Bool,
243
+ timingLabel: String
244
+ ) -> CVPixelBuffer? {
245
+ inFlightSemaphore.wait()
246
+ commandBuffer.addCompletedHandler { [weak self] completed in
247
+ // Hold the per-frame inputs/wrappers until the GPU finishes. Referencing
248
+ // `keepAlive` inside the closure is the entire point: it extends their
249
+ // lifetime to command-buffer completion. Touched but intentionally unused.
250
+ _ = keepAlive
251
+ guard let self else { return }
252
+ if debugTiming {
253
+ let gpuMs = (completed.gpuEndTime - completed.gpuStartTime) * 1000.0
254
+ os_log("%{public}@ gpu: %.2f ms", log: MetalRenderer.perfLog, type: .info,
255
+ timingLabel, gpuMs)
256
+ }
257
+ if completed.error == nil {
258
+ os_unfair_lock_lock(&pipelineLock)
259
+ readyOutput = currentOutput
260
+ os_unfair_lock_unlock(&pipelineLock)
261
+ } else {
262
+ os_log("%{public}@ command buffer error: %{public}@",
263
+ log: MetalRenderer.log, type: .error,
264
+ timingLabel, completed.error?.localizedDescription ?? "unknown")
265
+ }
266
+ inFlightSemaphore.signal()
267
+ }
268
+ commandBuffer.commit()
269
+
270
+ os_unfair_lock_lock(&pipelineLock)
271
+ let previous = readyOutput
272
+ os_unfair_lock_unlock(&pipelineLock)
273
+ return previous
344
274
  }
345
- return createdPool
346
- }
347
-
348
- // MARK: - Intermediate textures
349
-
350
- /// Dequeues a fresh "original" ingest buffer (BGRA, IOSurface-backed,
351
- /// Metal-compatible) from the pool and returns it with a per-frame Metal
352
- /// texture view and the CVMetalTexture wrapper that pins it to the IOSurface.
353
- /// The CVPixelBuffer is the CoreImage render target; the MTLTexture is a
354
- /// zero-copy view of the same IOSurface.
355
- ///
356
- /// The caller MUST keep `buffer` and `wrapper` alive until its command buffer
357
- /// completes (pass both in commitPipelined's keepAlive); the segmenter
358
- /// separately retains the buffer for its async read. The pool will not recycle
359
- /// the buffer until both readers release it. See the originalPool field
360
- /// comment for why this is pooled and not a single reused buffer.
361
- func originalIngestTarget(width: Int, height: Int) throws
362
- -> (buffer: CVPixelBuffer, texture: MTLTexture, wrapper: CVMetalTexture) {
363
- if originalPool == nil || originalPoolWidth != width || originalPoolHeight != height {
364
- // Worst-case live set is 4: 2 GPU-in-flight (semaphore value 2, each
365
- // pinned via keepAlive) + 1 the segmenter's async worker still holds + 1
366
- // dequeued this frame. The CVMetalTexture wrapper does not occupy its own
367
- // pool slot (it pins the same buffer's IOSurface). 5 leaves one of
368
- // headroom; the pool grows past the floor on demand regardless.
369
- originalPool = try MetalRenderer.makeBGRAMetalPool(width: width, height: height, minCount: 5)
370
- originalPoolWidth = width
371
- originalPoolHeight = height
372
- }
373
- guard let pool = originalPool else {
374
- throw RendererError.pixelBufferPoolCreateFailed(kCVReturnError)
275
+
276
+ // MARK: - Output buffer pool
277
+
278
+ /// Returns a fresh BGRA, IOSurface-backed, Metal-compatible CVPixelBuffer
279
+ /// from the pool, recreating the pool if dimensions changed. The pool keeps
280
+ /// allocation off the per-frame hot path; the buffer is owned by the caller
281
+ /// and released when the RTCVideoFrame that wraps it is released.
282
+ func dequeueOutputBuffer(width: Int, height: Int) throws -> CVPixelBuffer {
283
+ if outputPool == nil || poolWidth != width || poolHeight != height {
284
+ try rebuildOutputPool(width: width, height: height)
285
+ }
286
+ guard let pool = outputPool else {
287
+ throw RendererError.pixelBufferPoolCreateFailed(kCVReturnError)
288
+ }
289
+ var pixelBuffer: CVPixelBuffer?
290
+ let status = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pool, &pixelBuffer)
291
+ guard status == kCVReturnSuccess, let buffer = pixelBuffer else {
292
+ throw RendererError.pixelBufferAllocFailed(status)
293
+ }
294
+ return buffer
375
295
  }
376
- var pixelBuffer: CVPixelBuffer?
377
- let status = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pool, &pixelBuffer)
378
- guard status == kCVReturnSuccess, let buffer = pixelBuffer else {
379
- throw RendererError.pixelBufferAllocFailed(status)
296
+
297
+ private func rebuildOutputPool(width: Int, height: Int) throws {
298
+ // min 4 covers the worst-case live set now that the completion handler
299
+ // retains `currentOutput` until the GPU finishes: the semaphore (value 2)
300
+ // permits TWO command buffers in flight, so two distinct `currentOutput`
301
+ // buffers can be captured at once, PLUS the previously-published
302
+ // `readyOutput` the capture thread may still be handing to WebRTC, PLUS the
303
+ // one being dequeued this frame. 2 + 1 + 1 = 4. The pool grows past the
304
+ // minimum if all are momentarily live, so 4 is the steady-state floor, not a
305
+ // hard cap.
306
+ outputPool = try MetalRenderer.makeBGRAMetalPool(width: width, height: height, minCount: 4)
307
+ poolWidth = width
308
+ poolHeight = height
380
309
  }
381
- let (texture, wrapper) = try TextureBridge.makeTexture(
382
- from: buffer,
383
- cache: textureCache,
384
- pixelFormat: .bgra8Unorm,
385
- planeIndex: 0
386
- )
387
- return (buffer, texture, wrapper)
388
- }
389
-
390
- /// Returns the two blur ping-pong textures, allocating on first use or on
391
- /// resolution change.
392
- func blurPingPong(width: Int, height: Int) throws -> (MTLTexture, MTLTexture) {
393
- if let a = blurTexA, let b = blurTexB, blurTexWidth == width, blurTexHeight == height {
394
- return (a, b)
310
+
311
+ /// Creates a CVPixelBufferPool of BGRA, IOSurface-backed, Metal-compatible
312
+ /// buffers. Shared by the output pool and the original-ingest pool. IOSurface-
313
+ /// backed so downstream (RTCCVPixelBuffer -> I420 -> encoder) accepts the
314
+ /// buffer; Metal-compatible so CVMetalTextureCache can wrap it as a texture
315
+ /// without a copy. Pools grow past `minCount` if more buffers are momentarily
316
+ /// live, so the count is a steady-state floor, not a hard cap.
317
+ private static func makeBGRAMetalPool(width: Int, height: Int, minCount: Int) throws
318
+ -> CVPixelBufferPool
319
+ {
320
+ let pixelBufferAttributes: [String: Any] = [
321
+ kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA,
322
+ kCVPixelBufferWidthKey as String: width,
323
+ kCVPixelBufferHeightKey as String: height,
324
+ kCVPixelBufferIOSurfacePropertiesKey as String: [String: Any](),
325
+ kCVPixelBufferMetalCompatibilityKey as String: true
326
+ ]
327
+ let poolAttributes: [String: Any] = [
328
+ kCVPixelBufferPoolMinimumBufferCountKey as String: minCount
329
+ ]
330
+ var pool: CVPixelBufferPool?
331
+ let status = CVPixelBufferPoolCreate(
332
+ kCFAllocatorDefault,
333
+ poolAttributes as CFDictionary,
334
+ pixelBufferAttributes as CFDictionary,
335
+ &pool
336
+ )
337
+ guard status == kCVReturnSuccess, let createdPool = pool else {
338
+ throw RendererError.pixelBufferPoolCreateFailed(status)
339
+ }
340
+ return createdPool
395
341
  }
396
- let a = try makeRenderTargetTexture(width: width, height: height)
397
- let b = try makeRenderTargetTexture(width: width, height: height)
398
- blurTexA = a
399
- blurTexB = b
400
- blurTexWidth = width
401
- blurTexHeight = height
402
- return (a, b)
403
- }
404
-
405
- private func makeRenderTargetTexture(width: Int, height: Int) throws -> MTLTexture {
406
- let desc = MTLTextureDescriptor.texture2DDescriptor(
407
- pixelFormat: .bgra8Unorm,
408
- width: width,
409
- height: height,
410
- mipmapped: false
411
- )
412
- desc.usage = [.renderTarget, .shaderRead]
413
- desc.storageMode = .private
414
- guard let tex = device.makeTexture(descriptor: desc) else {
415
- throw RendererError.textureBindFailed("makeTexture (render target) returned nil")
342
+
343
+ // MARK: - Intermediate textures
344
+
345
+ /// Dequeues a fresh "original" ingest buffer (BGRA, IOSurface-backed,
346
+ /// Metal-compatible) from the pool and returns it with a per-frame Metal
347
+ /// texture view and the CVMetalTexture wrapper that pins it to the IOSurface.
348
+ /// The CVPixelBuffer is the CoreImage render target; the MTLTexture is a
349
+ /// zero-copy view of the same IOSurface.
350
+ ///
351
+ /// The caller MUST keep `buffer` and `wrapper` alive until its command buffer
352
+ /// completes (pass both in commitPipelined's keepAlive); the segmenter
353
+ /// separately retains the buffer for its async read. The pool will not recycle
354
+ /// the buffer until both readers release it. See the originalPool field
355
+ /// comment for why this is pooled and not a single reused buffer.
356
+ func originalIngestTarget(width: Int, height: Int) throws
357
+ -> (buffer: CVPixelBuffer, texture: MTLTexture, wrapper: CVMetalTexture)
358
+ {
359
+ if originalPool == nil || originalPoolWidth != width || originalPoolHeight != height {
360
+ // Worst-case live set is 4: 2 GPU-in-flight (semaphore value 2, each
361
+ // pinned via keepAlive) + 1 the segmenter's async worker still holds + 1
362
+ // dequeued this frame. The CVMetalTexture wrapper does not occupy its own
363
+ // pool slot (it pins the same buffer's IOSurface). 5 leaves one of
364
+ // headroom; the pool grows past the floor on demand regardless.
365
+ originalPool = try MetalRenderer.makeBGRAMetalPool(width: width, height: height, minCount: 5)
366
+ originalPoolWidth = width
367
+ originalPoolHeight = height
368
+ }
369
+ guard let pool = originalPool else {
370
+ throw RendererError.pixelBufferPoolCreateFailed(kCVReturnError)
371
+ }
372
+ var pixelBuffer: CVPixelBuffer?
373
+ let status = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pool, &pixelBuffer)
374
+ guard status == kCVReturnSuccess, let buffer = pixelBuffer else {
375
+ throw RendererError.pixelBufferAllocFailed(status)
376
+ }
377
+ let (texture, wrapper) = try TextureBridge.makeTexture(
378
+ from: buffer,
379
+ cache: textureCache,
380
+ pixelFormat: .bgra8Unorm,
381
+ planeIndex: 0
382
+ )
383
+ return (buffer, texture, wrapper)
416
384
  }
417
- return tex
418
- }
419
-
420
- // MARK: - Draw helpers
421
-
422
- /// Encodes a fullscreen-triangle draw into `target` using the given
423
- /// pipeline. The caller binds fragment buffers/textures/samplers via the
424
- /// `configure` closure. Loads the attachment as `.dontCare` (we overwrite
425
- /// every texel) and stores it.
426
- func drawFullscreen(
427
- commandBuffer: MTLCommandBuffer,
428
- pipeline: MTLRenderPipelineState,
429
- target: MTLTexture,
430
- label: String,
431
- configure: (MTLRenderCommandEncoder) -> Void
432
- ) throws {
433
- let passDesc = MTLRenderPassDescriptor()
434
- passDesc.colorAttachments[0].texture = target
435
- passDesc.colorAttachments[0].loadAction = .dontCare
436
- passDesc.colorAttachments[0].storeAction = .store
437
- guard let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: passDesc) else {
438
- throw RendererError.commandBufferUnavailable
385
+
386
+ private func makeRenderTargetTexture(width: Int, height: Int) throws -> MTLTexture {
387
+ let desc = MTLTextureDescriptor.texture2DDescriptor(
388
+ pixelFormat: .bgra8Unorm,
389
+ width: width,
390
+ height: height,
391
+ mipmapped: false
392
+ )
393
+ desc.usage = [.renderTarget, .shaderRead]
394
+ desc.storageMode = .private
395
+ guard let tex = device.makeTexture(descriptor: desc) else {
396
+ throw RendererError.textureBindFailed("makeTexture (render target) returned nil")
397
+ }
398
+ return tex
439
399
  }
440
- encoder.label = label
441
- encoder.setRenderPipelineState(pipeline)
442
- configure(encoder)
443
- // Fullscreen quad via 4-vertex triangle strip. The passthrough vertex
444
- // shader (shaders/passthrough.vert) computes both gl_Position and vUv
445
- // from gl_VertexID alone for IDs 0..3, forming a quad that covers the
446
- // full NDC viewport. A 3-vertex .triangle call here would draw only
447
- // half the screen — the triangle ((-1,-1), (1,-1), (-1,1)) — with the
448
- // hypotenuse cutting diagonally across the frame, the SYMPTOM that
449
- // motivated this fix (half-black with diagonal staircase aliasing).
450
- encoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)
451
- encoder.endEncoding()
452
- }
453
-
454
- /// Encode one separable blur pass (`source` -> `target`) along `axis`.
455
- /// Binds the 5-float weights at buffer(0), the float2 axis at buffer(5), and
456
- /// the 5-float offsets at buffer(6), matching the regenerated blur.metalsrc.
457
- /// spirv-cross numbers uAxis/uOffsets right after the uWeights array, so
458
- /// these indices track the array size (was 0/9/10 at 9 entries). setFragment-
459
- /// Bytes uses each array's contiguous byte layout (length: ptr.count), so the
460
- /// byte count adapts on its own.
461
- func encodeBlurPass(
462
- commandBuffer: MTLCommandBuffer,
463
- source: MTLTexture,
464
- target: MTLTexture,
465
- kernel: BlurKernel,
466
- axis: SIMD2<Float>,
467
- label: String
468
- ) throws {
469
- try drawFullscreen(
470
- commandBuffer: commandBuffer,
471
- pipeline: blurPipeline,
472
- target: target,
473
- label: label
474
- ) { encoder in
475
- // spvUnsafeArray<float,5> is 5 tightly packed floats (20 bytes). A Swift
476
- // [Float] of 5 elements is contiguous with stride 4, so withUnsafeBytes
477
- // hands setFragmentBytes the exact 20-byte layout the shader expects.
478
- kernel.weights.withUnsafeBytes { ptr in
479
- encoder.setFragmentBytes(ptr.baseAddress!, length: ptr.count, index: 0)
480
- }
481
- var axisVar = axis
482
- encoder.setFragmentBytes(&axisVar, length: MemoryLayout<SIMD2<Float>>.stride, index: 5)
483
- kernel.offsets.withUnsafeBytes { ptr in
484
- encoder.setFragmentBytes(ptr.baseAddress!, length: ptr.count, index: 6)
485
- }
486
- encoder.setFragmentTexture(source, index: 0)
487
- encoder.setFragmentSamplerState(linearClampSampler, index: 0)
400
+
401
+ // MARK: - Draw helpers
402
+
403
+ /// Encodes a fullscreen-triangle draw into `target` using the given
404
+ /// pipeline. The caller binds fragment buffers/textures/samplers via the
405
+ /// `configure` closure. Loads the attachment as `.dontCare` (we overwrite
406
+ /// every texel) and stores it.
407
+ func drawFullscreen(
408
+ commandBuffer: MTLCommandBuffer,
409
+ pipeline: MTLRenderPipelineState,
410
+ target: MTLTexture,
411
+ label: String,
412
+ configure: (MTLRenderCommandEncoder) -> Void
413
+ ) throws {
414
+ let passDesc = MTLRenderPassDescriptor()
415
+ passDesc.colorAttachments[0].texture = target
416
+ passDesc.colorAttachments[0].loadAction = .dontCare
417
+ passDesc.colorAttachments[0].storeAction = .store
418
+ guard let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: passDesc) else {
419
+ throw RendererError.commandBufferUnavailable
420
+ }
421
+ encoder.label = label
422
+ encoder.setRenderPipelineState(pipeline)
423
+ configure(encoder)
424
+ // Fullscreen quad via 4-vertex triangle strip. The passthrough vertex
425
+ // shader (shaders/passthrough.vert) computes both gl_Position and vUv
426
+ // from gl_VertexID alone for IDs 0..3, forming a quad that covers the
427
+ // full NDC viewport. A 3-vertex .triangle call here would draw only
428
+ // half the screen, the triangle ((-1,-1), (1,-1), (-1,1)), with the
429
+ // hypotenuse cutting diagonally across the frame, the SYMPTOM that
430
+ // motivated this fix (half-black with diagonal staircase aliasing).
431
+ encoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)
432
+ encoder.endEncoding()
488
433
  }
489
- }
490
-
491
- /// Encode the composite pass into `target`.
492
- /// composite.metal bindings: buffer(0) uMaskUvScale, (1) uMaskUvOffset,
493
- /// (2) uMaskHi, (3) uMaskLo, (4) uBgUvScale, (5) uBgUvOffset; texture(0)
494
- /// uMask, (1) uOriginal, (2) uBackground; samplers 0/1/2.
495
- func encodeComposite(
496
- commandBuffer: MTLCommandBuffer,
497
- target: MTLTexture,
498
- original: MTLTexture,
499
- background: MTLTexture,
500
- mask: MTLTexture,
501
- maskUvScale: SIMD2<Float>,
502
- maskUvOffset: SIMD2<Float>,
503
- maskHi: Float,
504
- maskLo: Float,
505
- bgUvScale: SIMD2<Float>,
506
- bgUvOffset: SIMD2<Float>,
507
- label: String
508
- ) throws {
509
- try drawFullscreen(
510
- commandBuffer: commandBuffer,
511
- pipeline: compositePipeline,
512
- target: target,
513
- label: label
514
- ) { encoder in
515
- var maskUvScaleVar = maskUvScale
516
- var maskUvOffsetVar = maskUvOffset
517
- var maskHiVar = maskHi
518
- var maskLoVar = maskLo
519
- var bgUvScaleVar = bgUvScale
520
- var bgUvOffsetVar = bgUvOffset
521
- encoder.setFragmentBytes(&maskUvScaleVar, length: MemoryLayout<SIMD2<Float>>.stride, index: 0)
522
- encoder.setFragmentBytes(&maskUvOffsetVar, length: MemoryLayout<SIMD2<Float>>.stride, index: 1)
523
- encoder.setFragmentBytes(&maskHiVar, length: MemoryLayout<Float>.stride, index: 2)
524
- encoder.setFragmentBytes(&maskLoVar, length: MemoryLayout<Float>.stride, index: 3)
525
- encoder.setFragmentBytes(&bgUvScaleVar, length: MemoryLayout<SIMD2<Float>>.stride, index: 4)
526
- encoder.setFragmentBytes(&bgUvOffsetVar, length: MemoryLayout<SIMD2<Float>>.stride, index: 5)
527
- encoder.setFragmentTexture(mask, index: 0)
528
- encoder.setFragmentTexture(original, index: 1)
529
- encoder.setFragmentTexture(background, index: 2)
530
- encoder.setFragmentSamplerState(linearClampSampler, index: 0)
531
- encoder.setFragmentSamplerState(linearClampSampler, index: 1)
532
- encoder.setFragmentSamplerState(linearClampSampler, index: 2)
434
+
435
+ // MARK: - Generic generative shader
436
+
437
+ /// Build a render pipeline for an arbitrary generative fragment shader, reusing
438
+ /// the shared passthrough vertex (fullscreen quad from gl_VertexID; no vertex
439
+ /// buffer). The owning ShaderProcessor calls this once at first frame with a
440
+ /// ShaderLibrary compiled from `<name>.metalsrc`, so there is NO per-shader
441
+ /// Swift here and adding a generative shader needs no renderer change. The
442
+ /// pipeline renders into a BGRA target like every other pass.
443
+ func makeGenerativePipeline(fragment: MTLFunction, label: String) throws
444
+ -> MTLRenderPipelineState
445
+ {
446
+ try MetalRenderer.makePipeline(
447
+ device: device,
448
+ vertex: passthroughVertex,
449
+ fragment: fragment,
450
+ label: label
451
+ )
533
452
  }
534
- }
535
-
536
- /// Encode the geometric transform pass (`source` -> `target`) for the flip /
537
- /// rotate effects. transform.metalsrc bindings: buffer(0) uUvTransform
538
- /// (float2x2), texture(0) uTex, sampler(0) uTexSmplr. The host computes
539
- /// `uvTransform` via the Orientation helper (the single source of the
540
- /// camera-buffer reorientation math). For the 90-degree rotations `target` is
541
- /// dimension-swapped (h x w) relative to `source`.
542
- func encodeTransform(
543
- commandBuffer: MTLCommandBuffer,
544
- source: MTLTexture,
545
- target: MTLTexture,
546
- uvTransform: simd_float2x2,
547
- label: String
548
- ) throws {
549
- try drawFullscreen(
550
- commandBuffer: commandBuffer,
551
- pipeline: transformPipeline,
552
- target: target,
553
- label: label
554
- ) { encoder in
555
- // simd_float2x2 is two contiguous float2 columns (16 bytes), the exact
556
- // layout MSL's `constant float2x2&` expects at buffer(0).
557
- var uvTransformVar = uvTransform
558
- encoder.setFragmentBytes(
559
- &uvTransformVar,
560
- length: MemoryLayout<simd_float2x2>.stride,
561
- index: 0
562
- )
563
- encoder.setFragmentTexture(source, index: 0)
564
- encoder.setFragmentSamplerState(linearClampSampler, index: 0)
453
+
454
+ /// A BGRA, .private render-target texture for a generative shader's background
455
+ /// output. Same shape as the blur ping-pong targets; the ShaderProcessor
456
+ /// caches one per resolution.
457
+ func makeGenerativeTarget(width: Int, height: Int) throws -> MTLTexture {
458
+ try makeRenderTargetTexture(width: width, height: height)
565
459
  }
566
- }
567
- }
568
460
 
569
- /// A linear-sampled separable Gaussian kernel: 5 entries (center + 4 bilinear
570
- /// pairs of dense texels). Mirrors BlurFactory.ensureKernel and
571
- /// src/web/blur-kernel.ts. Rebuilt only when sigma changes.
572
- struct BlurKernel {
573
- private(set) var weights = [Float](repeating: 0, count: 5)
574
- private(set) var offsets = [Float](repeating: 0, count: 5)
575
- private var cachedSigma: Float = .nan
576
-
577
- mutating func ensure(sigma: Float) {
578
- if sigma == cachedSigma { return }
579
- let s = Double(sigma)
580
- func g(_ t: Double) -> Double { exp(-(t * t) / (2.0 * s * s)) }
581
- // Linear-sampled: center + 4 bilinear pairs of dense texels (1,2)(3,4)
582
- // (5,6)(7,8). See src/web/blur-kernel.ts for the shared derivation.
583
- offsets[0] = 0
584
- weights[0] = Float(g(0))
585
- var sum = weights[0]
586
- for p in 1..<5 {
587
- let a = Double(2 * p - 1)
588
- let b = Double(2 * p)
589
- let wa = g(a)
590
- let wb = g(b)
591
- let w = wa + wb
592
- offsets[p] = Float((a * wa + b * wb) / w)
593
- weights[p] = Float(w)
594
- sum += 2.0 * weights[p]
461
+ /// Encode one generative fragment pass into `target`. Binds the host-provided
462
+ /// built-ins (uTime, uResolution) plus every JS-set uniform, each at the Metal
463
+ /// buffer index the shader's MSL decoration assigned it (see
464
+ /// ShaderLibrary.uniformBufferIndices). `scalarUniforms` and `vectorUniforms`
465
+ /// carry (bufferIndex, value) pairs already resolved by name on the host side,
466
+ /// so this method stays NAME-AGNOSTIC: it knows only indices and byte layouts,
467
+ /// never a uniform's meaning. A scalar binds as a single Float (4 bytes); a
468
+ /// 2/3/4-component vector binds as a tightly packed [Float] whose byte count is
469
+ /// the element count * 4; matching MSL's `constant float&` / `float2&` /
470
+ /// `float3&` / `float4&` argument layout (spirv-cross packs float3 as 16 bytes
471
+ /// in a buffer; see the float3 caveat in ShaderProcessor where the host pads).
472
+ func encodeGenerative(
473
+ commandBuffer: MTLCommandBuffer,
474
+ pipeline: MTLRenderPipelineState,
475
+ target: MTLTexture,
476
+ builtinBindings: [(index: Int, value: [Float])],
477
+ uniformBindings: [(index: Int, value: [Float])],
478
+ label: String
479
+ ) throws {
480
+ try drawFullscreen(
481
+ commandBuffer: commandBuffer,
482
+ pipeline: pipeline,
483
+ target: target,
484
+ label: label
485
+ ) { encoder in
486
+ for binding in builtinBindings {
487
+ binding.value.withUnsafeBytes { ptr in
488
+ encoder.setFragmentBytes(ptr.baseAddress!, length: ptr.count, index: binding.index)
489
+ }
490
+ }
491
+ for binding in uniformBindings {
492
+ binding.value.withUnsafeBytes { ptr in
493
+ encoder.setFragmentBytes(ptr.baseAddress!, length: ptr.count, index: binding.index)
494
+ }
495
+ }
496
+ }
595
497
  }
596
- if sum > 0 {
597
- for i in 0..<5 { weights[i] /= sum }
498
+
499
+ /// Encode the geometric transform pass (`source` -> `target`) for the flip /
500
+ /// rotate effects. transform.metalsrc bindings: buffer(0) uUvTransform
501
+ /// (float2x2), texture(0) uTex, sampler(0) uTexSmplr. The host computes
502
+ /// `uvTransform` via the Orientation helper (the single source of the
503
+ /// camera-buffer reorientation math). For the 90-degree rotations `target` is
504
+ /// dimension-swapped (h x w) relative to `source`.
505
+ func encodeTransform(
506
+ commandBuffer: MTLCommandBuffer,
507
+ source: MTLTexture,
508
+ target: MTLTexture,
509
+ uvTransform: simd_float2x2,
510
+ label: String
511
+ ) throws {
512
+ try drawFullscreen(
513
+ commandBuffer: commandBuffer,
514
+ pipeline: transformPipeline,
515
+ target: target,
516
+ label: label
517
+ ) { encoder in
518
+ // simd_float2x2 is two contiguous float2 columns (16 bytes), the exact
519
+ // layout MSL's `constant float2x2&` expects at buffer(0).
520
+ var uvTransformVar = uvTransform
521
+ encoder.setFragmentBytes(
522
+ &uvTransformVar,
523
+ length: MemoryLayout<simd_float2x2>.stride,
524
+ index: 0
525
+ )
526
+ encoder.setFragmentTexture(source, index: 0)
527
+ encoder.setFragmentSamplerState(linearClampSampler, index: 0)
528
+ }
598
529
  }
599
- cachedSigma = sigma
600
- }
601
530
  }