@bloopjs/toodle 0.0.100

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 (358) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +44 -0
  3. package/dist/Toodle.d.ts +304 -0
  4. package/dist/Toodle.d.ts.map +1 -0
  5. package/dist/colors/mod.d.ts +872 -0
  6. package/dist/colors/mod.d.ts.map +1 -0
  7. package/dist/coreTypes/Color.d.ts +7 -0
  8. package/dist/coreTypes/Color.d.ts.map +1 -0
  9. package/dist/coreTypes/Point.d.ts +8 -0
  10. package/dist/coreTypes/Point.d.ts.map +1 -0
  11. package/dist/coreTypes/Size.d.ts +5 -0
  12. package/dist/coreTypes/Size.d.ts.map +1 -0
  13. package/dist/coreTypes/Transform.d.ts +16 -0
  14. package/dist/coreTypes/Transform.d.ts.map +1 -0
  15. package/dist/coreTypes/Vec2.d.ts +8 -0
  16. package/dist/coreTypes/Vec2.d.ts.map +1 -0
  17. package/dist/coreTypes/mod.d.ts +6 -0
  18. package/dist/coreTypes/mod.d.ts.map +1 -0
  19. package/dist/docs/snippets/add-remove-children.d.ts +1 -0
  20. package/dist/docs/snippets/basic-quad.d.ts +1 -0
  21. package/dist/docs/snippets/filter-linear.d.ts +1 -0
  22. package/dist/docs/snippets/filter-nearest.d.ts +1 -0
  23. package/dist/docs/snippets/flipxy.d.ts +1 -0
  24. package/dist/docs/snippets/hello-text.d.ts +1 -0
  25. package/dist/docs/snippets/jumbo-textures.d.ts +1 -0
  26. package/dist/docs/snippets/layer.d.ts +1 -0
  27. package/dist/docs/snippets/layout-edges.d.ts +1 -0
  28. package/dist/docs/snippets/layout-screen-and-world-space.d.ts +1 -0
  29. package/dist/docs/snippets/postprocess.d.ts +1 -0
  30. package/dist/docs/snippets/quad-size-scale.d.ts +1 -0
  31. package/dist/docs/snippets/quickstart.d.ts +1 -0
  32. package/dist/docs/snippets/repeat-texture-loading.d.ts +1 -0
  33. package/dist/docs/snippets/screen-shaders.d.ts +1 -0
  34. package/dist/docs/snippets/shader-color-flash.d.ts +1 -0
  35. package/dist/docs/snippets/shader-default.d.ts +1 -0
  36. package/dist/docs/snippets/shader-fill.d.ts +1 -0
  37. package/dist/docs/snippets/shapes-line.d.ts +1 -0
  38. package/dist/docs/snippets/sprite-region.d.ts +1 -0
  39. package/dist/docs/snippets/text-alignment.d.ts +1 -0
  40. package/dist/docs/snippets/text-shrink-to-fit.d.ts +1 -0
  41. package/dist/docs/snippets/text-word-wrap.d.ts +1 -0
  42. package/dist/docs/snippets/texture-bundles-prebaked.d.ts +1 -0
  43. package/dist/docs/snippets/texture-bundles.d.ts +1 -0
  44. package/dist/docs/snippets/transforms.d.ts +1 -0
  45. package/dist/docs/snippets/transparent-cropping.d.ts +1 -0
  46. package/dist/examples/0-hello.d.ts +1 -0
  47. package/dist/examples/1-hello.d.ts +1 -0
  48. package/dist/examples/1-hello.d.ts.map +1 -0
  49. package/dist/examples/1-quad.d.ts +1 -0
  50. package/dist/examples/10-resize.d.ts +1 -0
  51. package/dist/examples/10-resize.d.ts.map +1 -0
  52. package/dist/examples/11-bundle-test.d.ts +1 -0
  53. package/dist/examples/11-bundle-test.d.ts.map +1 -0
  54. package/dist/examples/12-transparent-pixel-cropping.d.ts +1 -0
  55. package/dist/examples/12-transparent-pixel-cropping.d.ts.map +1 -0
  56. package/dist/examples/13-crop.d.ts +1 -0
  57. package/dist/examples/13-crop.d.ts.map +1 -0
  58. package/dist/examples/14-bundle-bench.d.ts +1 -0
  59. package/dist/examples/14-bundle-bench.d.ts.map +1 -0
  60. package/dist/examples/15-text-layer.d.ts +1 -0
  61. package/dist/examples/15-text-layer.d.ts.map +1 -0
  62. package/dist/examples/16-jumbo-texture.d.ts +1 -0
  63. package/dist/examples/16-jumbo-textures.d.ts +1 -0
  64. package/dist/examples/16-screen-shader.d.ts +1 -0
  65. package/dist/examples/16-screen-shader.d.ts.map +1 -0
  66. package/dist/examples/17-lighting.d.ts +1 -0
  67. package/dist/examples/17-lighting.d.ts.map +1 -0
  68. package/dist/examples/17-translations.d.ts +1 -0
  69. package/dist/examples/18-blur.d.ts +1 -0
  70. package/dist/examples/19-postprocess.d.ts +1 -0
  71. package/dist/examples/19-screenshader.d.ts +1 -0
  72. package/dist/examples/2-shapes.d.ts +1 -0
  73. package/dist/examples/2-shapes.d.ts.map +1 -0
  74. package/dist/examples/3-shader.d.ts +1 -0
  75. package/dist/examples/3-shader.d.ts.map +1 -0
  76. package/dist/examples/4-shader-bench.d.ts +1 -0
  77. package/dist/examples/4-shader-bench.d.ts.map +1 -0
  78. package/dist/examples/5-z.d.ts +1 -0
  79. package/dist/examples/5-z.d.ts.map +1 -0
  80. package/dist/examples/6-atlas.d.ts +1 -0
  81. package/dist/examples/6-atlas.d.ts.map +1 -0
  82. package/dist/examples/7-text.d.ts +1 -0
  83. package/dist/examples/7-text.d.ts.map +1 -0
  84. package/dist/examples/8-text-bench.d.ts +1 -0
  85. package/dist/examples/8-text-bench.d.ts.map +1 -0
  86. package/dist/examples/9-alignment.d.ts +1 -0
  87. package/dist/examples/9-alignment.d.ts.map +1 -0
  88. package/dist/examples/main.d.ts +1 -0
  89. package/dist/examples/main.d.ts.map +1 -0
  90. package/dist/examples/util.d.ts +82 -0
  91. package/dist/examples/util.d.ts.map +1 -0
  92. package/dist/limits.d.ts +23 -0
  93. package/dist/limits.d.ts.map +1 -0
  94. package/dist/math/angle.d.ts +13 -0
  95. package/dist/math/angle.d.ts.map +1 -0
  96. package/dist/math/matrix.d.ts +26 -0
  97. package/dist/math/matrix.d.ts.map +1 -0
  98. package/dist/math/mod.d.ts +3 -0
  99. package/dist/math/mod.d.ts.map +1 -0
  100. package/dist/mod.d.ts +17 -0
  101. package/dist/mod.d.ts.map +1 -0
  102. package/dist/mod.js +19665 -0
  103. package/dist/mod.js.map +41 -0
  104. package/dist/postprocess.d.ts +10 -0
  105. package/dist/postprocess.d.ts.map +1 -0
  106. package/dist/scene/Batcher.d.ts +20 -0
  107. package/dist/scene/Batcher.d.ts.map +1 -0
  108. package/dist/scene/Camera.d.ts +16 -0
  109. package/dist/scene/Camera.d.ts.map +1 -0
  110. package/dist/scene/JumboQuadNode.d.ts +29 -0
  111. package/dist/scene/JumboQuadNode.d.ts.map +1 -0
  112. package/dist/scene/QuadNode.d.ts +159 -0
  113. package/dist/scene/QuadNode.d.ts.map +1 -0
  114. package/dist/scene/RenderComponent.d.ts +11 -0
  115. package/dist/scene/RenderComponent.d.ts.map +1 -0
  116. package/dist/scene/SceneNode.d.ts +300 -0
  117. package/dist/scene/SceneNode.d.ts.map +1 -0
  118. package/dist/scene/mod.d.ts +5 -0
  119. package/dist/scene/mod.d.ts.map +1 -0
  120. package/dist/screen/mod.d.ts +2 -0
  121. package/dist/screen/mod.d.ts.map +1 -0
  122. package/dist/screen/resolution.d.ts +5 -0
  123. package/dist/screen/resolution.d.ts.map +1 -0
  124. package/dist/shaders/EngineUniform.d.ts +9 -0
  125. package/dist/shaders/EngineUniform.d.ts.map +1 -0
  126. package/dist/shaders/IShader.d.ts +15 -0
  127. package/dist/shaders/IShader.d.ts.map +1 -0
  128. package/dist/shaders/QuadShader.d.ts +18 -0
  129. package/dist/shaders/QuadShader.d.ts.map +1 -0
  130. package/dist/shaders/ShaderDescriptor.d.ts +7 -0
  131. package/dist/shaders/ShaderDescriptor.d.ts.map +1 -0
  132. package/dist/shaders/mod.d.ts +6 -0
  133. package/dist/shaders/mod.d.ts.map +1 -0
  134. package/dist/shaders/parser.d.ts +8 -0
  135. package/dist/shaders/parser.d.ts.map +1 -0
  136. package/dist/shaders/postprocess/blur.d.ts +3 -0
  137. package/dist/shaders/postprocess/blur.d.ts.map +1 -0
  138. package/dist/shaders/postprocess/mod.d.ts +17 -0
  139. package/dist/shaders/postprocess/mod.d.ts.map +1 -0
  140. package/dist/shaders/samplers.d.ts +3 -0
  141. package/dist/shaders/samplers.d.ts.map +1 -0
  142. package/dist/shaders/wgsl/example.wgsl.d.ts +3 -0
  143. package/dist/shaders/wgsl/example.wgsl.d.ts.map +1 -0
  144. package/dist/shaders/wgsl/hello.wgsl.d.ts +3 -0
  145. package/dist/shaders/wgsl/hello.wgsl.d.ts.map +1 -0
  146. package/dist/shaders/wgsl/helloInstanced.wgsl.d.ts +3 -0
  147. package/dist/shaders/wgsl/helloInstanced.wgsl.d.ts.map +1 -0
  148. package/dist/shaders/wgsl/quad.wgsl.d.ts +3 -0
  149. package/dist/shaders/wgsl/quad.wgsl.d.ts.map +1 -0
  150. package/dist/src/Toodle.d.ts +303 -0
  151. package/dist/src/Toodle.d.ts.map +1 -0
  152. package/dist/src/colors/mod.d.ts +871 -0
  153. package/dist/src/coreTypes/Color.d.ts +6 -0
  154. package/dist/src/coreTypes/Color.d.ts.map +1 -0
  155. package/dist/src/coreTypes/Point.d.ts +7 -0
  156. package/dist/src/coreTypes/Point.d.ts.map +1 -0
  157. package/dist/src/coreTypes/Size.d.ts +4 -0
  158. package/dist/src/coreTypes/Size.d.ts.map +1 -0
  159. package/dist/src/coreTypes/Transform.d.ts +15 -0
  160. package/dist/src/coreTypes/Transform.d.ts.map +1 -0
  161. package/dist/src/coreTypes/Vec2.d.ts +7 -0
  162. package/dist/src/coreTypes/Vec2.d.ts.map +1 -0
  163. package/dist/src/coreTypes/mod.d.ts +5 -0
  164. package/dist/src/coreTypes/mod.d.ts.map +1 -0
  165. package/dist/src/limits.d.ts +22 -0
  166. package/dist/src/limits.d.ts.map +1 -0
  167. package/dist/src/math/angle.d.ts +12 -0
  168. package/dist/src/math/angle.d.ts.map +1 -0
  169. package/dist/src/math/matrix.d.ts +25 -0
  170. package/dist/src/math/matrix.d.ts.map +1 -0
  171. package/dist/src/math/mod.d.ts +2 -0
  172. package/dist/src/math/mod.d.ts.map +1 -0
  173. package/dist/src/mod.d.ts +16 -0
  174. package/dist/src/mod.d.ts.map +1 -0
  175. package/dist/src/postprocess.d.ts +10 -0
  176. package/dist/src/postprocess.d.ts.map +1 -0
  177. package/dist/src/scene/Batcher.d.ts +19 -0
  178. package/dist/src/scene/Batcher.d.ts.map +1 -0
  179. package/dist/src/scene/Camera.d.ts +15 -0
  180. package/dist/src/scene/Camera.d.ts.map +1 -0
  181. package/dist/src/scene/JumboQuadNode.d.ts +28 -0
  182. package/dist/src/scene/QuadNode.d.ts +158 -0
  183. package/dist/src/scene/QuadNode.d.ts.map +1 -0
  184. package/dist/src/scene/RenderComponent.d.ts +10 -0
  185. package/dist/src/scene/RenderComponent.d.ts.map +1 -0
  186. package/dist/src/scene/SceneNode.d.ts +299 -0
  187. package/dist/src/scene/SceneNode.d.ts.map +1 -0
  188. package/dist/src/scene/mod.d.ts +4 -0
  189. package/dist/src/scene/mod.d.ts.map +1 -0
  190. package/dist/src/screen/mod.d.ts +1 -0
  191. package/dist/src/screen/mod.d.ts.map +1 -0
  192. package/dist/src/screen/resolution.d.ts +4 -0
  193. package/dist/src/screen/resolution.d.ts.map +1 -0
  194. package/dist/src/shaders/EngineUniform.d.ts +8 -0
  195. package/dist/src/shaders/EngineUniform.d.ts.map +1 -0
  196. package/dist/src/shaders/IShader.d.ts +14 -0
  197. package/dist/src/shaders/IShader.d.ts.map +1 -0
  198. package/dist/src/shaders/QuadShader.d.ts +17 -0
  199. package/dist/src/shaders/QuadShader.d.ts.map +1 -0
  200. package/dist/src/shaders/ShaderDescriptor.d.ts +6 -0
  201. package/dist/src/shaders/ShaderDescriptor.d.ts.map +1 -0
  202. package/dist/src/shaders/mod.d.ts +5 -0
  203. package/dist/src/shaders/mod.d.ts.map +1 -0
  204. package/dist/src/shaders/parser.d.ts +7 -0
  205. package/dist/src/shaders/parser.d.ts.map +1 -0
  206. package/dist/src/shaders/postprocess/blur.d.ts +2 -0
  207. package/dist/src/shaders/postprocess/mod.d.ts +16 -0
  208. package/dist/src/shaders/postprocess/postprocess.d.ts +8 -0
  209. package/dist/src/shaders/postprocess/util.d.ts +2 -0
  210. package/dist/src/shaders/samplers.d.ts +2 -0
  211. package/dist/src/shaders/samplers.d.ts.map +1 -0
  212. package/dist/src/shaders/wgsl/example.wgsl.d.ts +2 -0
  213. package/dist/src/shaders/wgsl/example.wgsl.d.ts.map +1 -0
  214. package/dist/src/shaders/wgsl/hello.wgsl.d.ts +2 -0
  215. package/dist/src/shaders/wgsl/hello.wgsl.d.ts.map +1 -0
  216. package/dist/src/shaders/wgsl/helloInstanced.wgsl.d.ts +2 -0
  217. package/dist/src/shaders/wgsl/helloInstanced.wgsl.d.ts.map +1 -0
  218. package/dist/src/shaders/wgsl/quad.wgsl.d.ts +2 -0
  219. package/dist/src/shaders/wgsl/quad.wgsl.d.ts.map +1 -0
  220. package/dist/src/text/FontPipeline.d.ts +13 -0
  221. package/dist/src/text/FontPipeline.d.ts.map +1 -0
  222. package/dist/src/text/MsdfFont.d.ts +81 -0
  223. package/dist/src/text/MsdfFont.d.ts.map +1 -0
  224. package/dist/src/text/TextFormatting.d.ts +18 -0
  225. package/dist/src/text/TextFormatting.d.ts.map +1 -0
  226. package/dist/src/text/TextNode.d.ts +18 -0
  227. package/dist/src/text/TextNode.d.ts.map +1 -0
  228. package/dist/src/text/TextShader.d.ts +14 -0
  229. package/dist/src/text/TextShader.d.ts.map +1 -0
  230. package/dist/src/text/mod.d.ts +3 -0
  231. package/dist/src/text/mod.d.ts.map +1 -0
  232. package/dist/src/text/shaping.d.ts +38 -0
  233. package/dist/src/text/shaping.d.ts.map +1 -0
  234. package/dist/src/text/text.wgsl.d.ts +2 -0
  235. package/dist/src/text/text.wgsl.d.ts.map +1 -0
  236. package/dist/src/textures/AssetManager.d.ts +181 -0
  237. package/dist/src/textures/AssetManager.d.ts.map +1 -0
  238. package/dist/src/textures/NewTextureComputeShader.d.ts +28 -0
  239. package/dist/src/textures/TextureComputeShader.d.ts +20 -0
  240. package/dist/src/textures/TextureComputeShader.d.ts.map +1 -0
  241. package/dist/src/textures/crop.wgsl.d.ts +2 -0
  242. package/dist/src/textures/mod.d.ts +1 -0
  243. package/dist/src/textures/mod.d.ts.map +1 -0
  244. package/dist/src/textures/pixel-scraping.wgsl.d.ts +2 -0
  245. package/dist/src/textures/pixel-scraping.wgsl.d.ts.map +1 -0
  246. package/dist/src/textures/texture-processing.wgsl.d.ts +2 -0
  247. package/dist/src/textures/types.d.ts +176 -0
  248. package/dist/src/textures/types.d.ts.map +1 -0
  249. package/dist/src/textures/util.d.ts +7 -0
  250. package/dist/src/textures/util.d.ts.map +1 -0
  251. package/dist/src/utils/assert.d.ts +1 -0
  252. package/dist/src/utils/assert.d.ts.map +1 -0
  253. package/dist/src/utils/boilerplate.d.ts +10 -0
  254. package/dist/src/utils/boilerplate.d.ts.map +1 -0
  255. package/dist/src/utils/error.d.ts +7 -0
  256. package/dist/src/utils/error.d.ts.map +1 -0
  257. package/dist/src/utils/mod.d.ts +2 -0
  258. package/dist/src/utils/mod.d.ts.map +1 -0
  259. package/dist/src/utils/pool.d.ts +22 -0
  260. package/dist/src/utils/pool.d.ts.map +1 -0
  261. package/dist/test/math/matrix.test.d.ts +1 -0
  262. package/dist/test/scene/Batcher.test.d.ts +1 -0
  263. package/dist/test/scene/SceneNode.test.d.ts +1 -0
  264. package/dist/test/shader/parser.test.d.ts +1 -0
  265. package/dist/text/FontPipeline.d.ts +14 -0
  266. package/dist/text/FontPipeline.d.ts.map +1 -0
  267. package/dist/text/MsdfFont.d.ts +82 -0
  268. package/dist/text/MsdfFont.d.ts.map +1 -0
  269. package/dist/text/TextFormatting.d.ts +19 -0
  270. package/dist/text/TextFormatting.d.ts.map +1 -0
  271. package/dist/text/TextNode.d.ts +19 -0
  272. package/dist/text/TextNode.d.ts.map +1 -0
  273. package/dist/text/TextShader.d.ts +15 -0
  274. package/dist/text/TextShader.d.ts.map +1 -0
  275. package/dist/text/mod.d.ts +4 -0
  276. package/dist/text/mod.d.ts.map +1 -0
  277. package/dist/text/shaping.d.ts +39 -0
  278. package/dist/text/shaping.d.ts.map +1 -0
  279. package/dist/text/text.wgsl.d.ts +3 -0
  280. package/dist/text/text.wgsl.d.ts.map +1 -0
  281. package/dist/textures/AssetManager.d.ts +182 -0
  282. package/dist/textures/AssetManager.d.ts.map +1 -0
  283. package/dist/textures/TextureComputeShader.d.ts +21 -0
  284. package/dist/textures/TextureComputeShader.d.ts.map +1 -0
  285. package/dist/textures/mod.d.ts +2 -0
  286. package/dist/textures/mod.d.ts.map +1 -0
  287. package/dist/textures/pixel-scraping.wgsl.d.ts +3 -0
  288. package/dist/textures/pixel-scraping.wgsl.d.ts.map +1 -0
  289. package/dist/textures/types.d.ts +177 -0
  290. package/dist/textures/types.d.ts.map +1 -0
  291. package/dist/textures/util.d.ts +8 -0
  292. package/dist/textures/util.d.ts.map +1 -0
  293. package/dist/utils/assert.d.ts +2 -0
  294. package/dist/utils/assert.d.ts.map +1 -0
  295. package/dist/utils/boilerplate.d.ts +11 -0
  296. package/dist/utils/boilerplate.d.ts.map +1 -0
  297. package/dist/utils/error.d.ts +8 -0
  298. package/dist/utils/error.d.ts.map +1 -0
  299. package/dist/utils/mod.d.ts +3 -0
  300. package/dist/utils/mod.d.ts.map +1 -0
  301. package/dist/utils/pool.d.ts +23 -0
  302. package/dist/utils/pool.d.ts.map +1 -0
  303. package/package.json +47 -0
  304. package/src/Toodle.ts +853 -0
  305. package/src/colors/mod.ts +151 -0
  306. package/src/coreTypes/Color.ts +1 -0
  307. package/src/coreTypes/Point.ts +7 -0
  308. package/src/coreTypes/Size.ts +4 -0
  309. package/src/coreTypes/Transform.ts +16 -0
  310. package/src/coreTypes/Vec2.ts +7 -0
  311. package/src/coreTypes/mod.ts +5 -0
  312. package/src/globals.d.ts +4 -0
  313. package/src/limits.ts +23 -0
  314. package/src/math/angle.ts +17 -0
  315. package/src/math/matrix.ts +99 -0
  316. package/src/math/mod.ts +2 -0
  317. package/src/mod.ts +22 -0
  318. package/src/scene/Batcher.ts +61 -0
  319. package/src/scene/Camera.ts +69 -0
  320. package/src/scene/JumboQuadNode.ts +219 -0
  321. package/src/scene/QuadNode.ts +403 -0
  322. package/src/scene/RenderComponent.ts +12 -0
  323. package/src/scene/SceneNode.ts +668 -0
  324. package/src/scene/mod.ts +4 -0
  325. package/src/screen/mod.ts +1 -0
  326. package/src/screen/resolution.ts +1 -0
  327. package/src/shaders/EngineUniform.ts +11 -0
  328. package/src/shaders/IShader.ts +20 -0
  329. package/src/shaders/QuadShader.ts +288 -0
  330. package/src/shaders/ShaderDescriptor.ts +6 -0
  331. package/src/shaders/mod.ts +5 -0
  332. package/src/shaders/parser.ts +221 -0
  333. package/src/shaders/postprocess/blur.ts +245 -0
  334. package/src/shaders/postprocess/mod.ts +71 -0
  335. package/src/shaders/samplers.ts +13 -0
  336. package/src/shaders/wgsl/example.wgsl.ts +24 -0
  337. package/src/shaders/wgsl/hello.wgsl.ts +62 -0
  338. package/src/shaders/wgsl/helloInstanced.wgsl.ts +46 -0
  339. package/src/shaders/wgsl/quad.wgsl.ts +140 -0
  340. package/src/text/FontPipeline.ts +212 -0
  341. package/src/text/MsdfFont.ts +190 -0
  342. package/src/text/TextFormatting.ts +28 -0
  343. package/src/text/TextNode.ts +82 -0
  344. package/src/text/TextShader.ts +223 -0
  345. package/src/text/mod.ts +8 -0
  346. package/src/text/shaping.ts +280 -0
  347. package/src/text/text.wgsl.ts +149 -0
  348. package/src/textures/AssetManager.ts +746 -0
  349. package/src/textures/TextureComputeShader.ts +434 -0
  350. package/src/textures/mod.ts +1 -0
  351. package/src/textures/pixel-scraping.wgsl.ts +131 -0
  352. package/src/textures/types.ts +182 -0
  353. package/src/textures/util.ts +352 -0
  354. package/src/utils/assert.ts +5 -0
  355. package/src/utils/boilerplate.ts +110 -0
  356. package/src/utils/error.ts +14 -0
  357. package/src/utils/mod.ts +2 -0
  358. package/src/utils/pool.ts +42 -0
@@ -0,0 +1,223 @@
1
+ import { WgslReflect } from "wgsl_reflect";
2
+ import type { SceneNode } from "../scene/SceneNode";
3
+ import type { EngineUniform } from "../shaders/EngineUniform";
4
+ import type { IShader } from "../shaders/IShader";
5
+ import type { FontPipeline } from "./FontPipeline";
6
+ import type { MsdfFont } from "./MsdfFont";
7
+ import { findLargestFontSize, measureText, shapeText } from "./shaping";
8
+ import { DEFAULT_FONT_SIZE, TextNode } from "./TextNode";
9
+ import msdfShader from "./text.wgsl";
10
+
11
+ const deets = new WgslReflect(msdfShader);
12
+ const struct = deets.structs.find((s) => s.name === "TextBlockDescriptor");
13
+ if (!struct) {
14
+ throw new Error("FormattedText struct not found");
15
+ }
16
+ const textDescriptorInstanceSize = struct.size;
17
+
18
+ export class TextShader implements IShader {
19
+ #device: GPUDevice;
20
+ #pipeline: GPURenderPipeline;
21
+ #bindGroups: GPUBindGroup[] = [];
22
+ #font: MsdfFont;
23
+ #maxCharCount: number;
24
+ #engineUniformsBuffer: GPUBuffer;
25
+ #descriptorBuffer: GPUBuffer;
26
+ #textBlockBuffer: GPUBuffer;
27
+ #cpuDescriptorBuffer: Float32Array;
28
+ #cpuTextBlockBuffer: Float32Array;
29
+ #instanceIndex = 0;
30
+ #textBlockOffset = 0;
31
+
32
+ constructor(
33
+ device: GPUDevice,
34
+ pipeline: FontPipeline,
35
+ font: MsdfFont,
36
+ colorFormat: GPUTextureFormat,
37
+ instanceCount: number,
38
+ ) {
39
+ this.#device = device;
40
+ this.#font = font;
41
+ this.#pipeline = pipeline.pipeline;
42
+ this.#maxCharCount = pipeline.maxCharCount;
43
+
44
+ this.#descriptorBuffer = device.createBuffer({
45
+ label: "msdf text descriptor buffer",
46
+ size: textDescriptorInstanceSize * instanceCount,
47
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
48
+ });
49
+
50
+ this.#cpuDescriptorBuffer = new Float32Array(
51
+ (instanceCount * textDescriptorInstanceSize) /
52
+ Float32Array.BYTES_PER_ELEMENT,
53
+ );
54
+
55
+ this.#cpuTextBlockBuffer = new Float32Array(
56
+ instanceCount * this.maxCharCount * 4,
57
+ );
58
+
59
+ this.#engineUniformsBuffer = device.createBuffer({
60
+ label: "msdf view projection matrix",
61
+ size: Float32Array.BYTES_PER_ELEMENT * 12,
62
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
63
+ });
64
+
65
+ this.#textBlockBuffer = device.createBuffer({
66
+ label: "msdf text buffer",
67
+ size:
68
+ instanceCount * this.maxCharCount * 4 * Float32Array.BYTES_PER_ELEMENT,
69
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
70
+ });
71
+
72
+ // create uniform bind groups
73
+ this.#bindGroups.push(pipeline.fontBindGroup);
74
+
75
+ this.#bindGroups.push(
76
+ device.createBindGroup({
77
+ label: "msdf text bind group",
78
+ layout: pipeline.pipeline.getBindGroupLayout(1),
79
+ entries: [
80
+ {
81
+ binding: 0,
82
+ resource: { buffer: this.#descriptorBuffer },
83
+ },
84
+ {
85
+ binding: 1,
86
+ resource: { buffer: this.#textBlockBuffer },
87
+ },
88
+ ],
89
+ }),
90
+ );
91
+
92
+ const engineUniformsBindGroup = device.createBindGroup({
93
+ label: "msdf text uniforms bind group",
94
+ layout: pipeline.pipeline.getBindGroupLayout(2),
95
+ entries: [
96
+ {
97
+ binding: 0,
98
+ resource: { buffer: this.#engineUniformsBuffer },
99
+ },
100
+ ],
101
+ });
102
+ this.#bindGroups.push(engineUniformsBindGroup);
103
+ }
104
+
105
+ startFrame(device: GPUDevice, uniform: EngineUniform): void {
106
+ device.queue.writeBuffer(
107
+ this.#engineUniformsBuffer,
108
+ 0,
109
+ uniform.viewProjectionMatrix as Float32Array,
110
+ );
111
+ this.#instanceIndex = 0;
112
+ this.#textBlockOffset = 0;
113
+ }
114
+
115
+ processBatch(renderPass: GPURenderPassEncoder, nodes: SceneNode[]): number {
116
+ if (nodes.length === 0) return 0;
117
+
118
+ renderPass.setPipeline(this.#pipeline);
119
+ for (let i = 0; i < this.#bindGroups.length; i++) {
120
+ renderPass.setBindGroup(i, this.#bindGroups[i]);
121
+ }
122
+
123
+ for (const node of nodes) {
124
+ if (!(node instanceof TextNode)) {
125
+ console.error(node);
126
+ throw new Error(
127
+ `Tried to use TextShader on something that isn't a TextNode: ${node}`,
128
+ );
129
+ }
130
+ const text = node.text;
131
+ const formatting = node.formatting;
132
+ const measurements = measureText(this.#font, text, formatting.wordWrap);
133
+
134
+ const textBlockSize = 4 * text.length;
135
+
136
+ // Calculate the buffer offset to get the current TextBlockDescriptor
137
+ const textDescriptorOffset =
138
+ (this.#instanceIndex * textDescriptorInstanceSize) /
139
+ Float32Array.BYTES_PER_ELEMENT;
140
+
141
+ // Shape text and pack to the buffer...
142
+ this.#cpuDescriptorBuffer.set(node.matrix, textDescriptorOffset);
143
+
144
+ // Color
145
+ this.#cpuDescriptorBuffer.set(
146
+ [node.tint.r, node.tint.g, node.tint.b, node.tint.a],
147
+ textDescriptorOffset + 12,
148
+ );
149
+
150
+ // Font Size
151
+ const size = node.size ?? measurements;
152
+ const fontSize = formatting.shrinkToFit
153
+ ? findLargestFontSize(this.#font, text, size, formatting)
154
+ : formatting.fontSize;
155
+ const actualFontSize = fontSize || DEFAULT_FONT_SIZE;
156
+ this.#cpuDescriptorBuffer[textDescriptorOffset + 16] = actualFontSize;
157
+
158
+ // Alignment and dimensions
159
+ this.#cpuDescriptorBuffer[textDescriptorOffset + 17] =
160
+ formatting.align === "center" ? 0 : measurements.width;
161
+ this.#cpuDescriptorBuffer[textDescriptorOffset + 18] =
162
+ measurements.height;
163
+
164
+ // Text block buffer offset
165
+ // the shader at text.wgsl.ts is expecting an index into the text block buffer,
166
+ // which is an array<vec4f> hence the division by 4
167
+ this.#cpuDescriptorBuffer[textDescriptorOffset + 19] =
168
+ this.#textBlockOffset / 4;
169
+
170
+ shapeText(
171
+ this.#font,
172
+ text,
173
+ size,
174
+ actualFontSize,
175
+ formatting,
176
+ this.#cpuTextBlockBuffer,
177
+ this.#textBlockOffset,
178
+ );
179
+
180
+ // Write instance data
181
+ this.#device.queue.writeBuffer(
182
+ this.#descriptorBuffer,
183
+ textDescriptorOffset * Float32Array.BYTES_PER_ELEMENT,
184
+ this.#cpuDescriptorBuffer,
185
+ textDescriptorOffset,
186
+ textDescriptorInstanceSize / Float32Array.BYTES_PER_ELEMENT,
187
+ );
188
+
189
+ this.#device.queue.writeBuffer(
190
+ this.#textBlockBuffer,
191
+ this.#textBlockOffset * Float32Array.BYTES_PER_ELEMENT,
192
+ this.#cpuTextBlockBuffer,
193
+ this.#textBlockOffset,
194
+ textBlockSize,
195
+ );
196
+
197
+ this.#textBlockOffset += textBlockSize;
198
+
199
+ // Draw text
200
+ renderPass.draw(
201
+ 4,
202
+ measurements.printedCharCount,
203
+ 4 * this.#instanceIndex,
204
+ 0,
205
+ );
206
+ this.#instanceIndex++;
207
+ }
208
+
209
+ return nodes.length;
210
+ }
211
+
212
+ endFrame(): void {
213
+ // No cleanup needed
214
+ }
215
+
216
+ get font() {
217
+ return this.#font;
218
+ }
219
+
220
+ get maxCharCount() {
221
+ return this.#maxCharCount;
222
+ }
223
+ }
@@ -0,0 +1,8 @@
1
+ // references:
2
+ // https://tchayen.com/drawing-text-in-webgpu-using-just-the-font-file
3
+ // https://github.com/Chlumsky/msdfgen/issues/22#issuecomment-234958005
4
+ // https://github.com/pixijs/pixijs/blob/dev/src/scene/text-bitmap/utils/getBitmapTextLayout.ts#L20
5
+
6
+ export type { TextOptions } from "./TextNode";
7
+ export { TextNode } from "./TextNode";
8
+ export { TextShader } from "./TextShader";
@@ -0,0 +1,280 @@
1
+ import type { Size } from "../coreTypes/Size";
2
+ import { type MsdfChar, type MsdfFont, WhitespaceKeyCodes } from "./MsdfFont";
3
+ import type { TextFormatting, WordWrapOptions } from "./TextFormatting";
4
+
5
+ // shaping is responsible for cpu-side text shaping:
6
+ // - measuring a text block
7
+ // - calculating the glyph quads for the text block
8
+ // - applying word wrap, shrink-to-fit, justification and other formatting options
9
+ // - returning the text measurements and glyph quads
10
+ const TAB_SPACES = 4;
11
+
12
+ export interface MsdfTextMeasurements {
13
+ /** The width of the text block in em units. */
14
+ width: number;
15
+ /** The height of the text block in em units. */
16
+ height: number;
17
+ /** The width of each line in em units. */
18
+ lineWidths: number[];
19
+ /** The number of lines in the text block. */
20
+ lineCount: number;
21
+ /** The number of characters printed in the text block. */
22
+ printedCharCount: number;
23
+
24
+ /** All words in the text block */
25
+ words: Word[];
26
+ }
27
+
28
+ export type Glyph = {
29
+ char: MsdfChar;
30
+ offset: [number, number];
31
+ line: number;
32
+ };
33
+
34
+ export type Word = {
35
+ glyphs: Glyph[];
36
+ width: number;
37
+ startX: number;
38
+ startY: number;
39
+ };
40
+
41
+ export function shapeText(
42
+ font: MsdfFont,
43
+ text: string,
44
+ blockSize: Size,
45
+ fontSize: number,
46
+ formatting: TextFormatting,
47
+ textArray: Float32Array,
48
+ initialFloatOffset = 0,
49
+ debug = false,
50
+ ) {
51
+ let offset = initialFloatOffset;
52
+
53
+ const measurements = measureText(font, text, formatting.wordWrap);
54
+ const alignment = formatting.align || "left";
55
+ const em2px = fontSize / font.lineHeight;
56
+ // currently there is a code path that sets blockSize.width to measurements.width (em)
57
+ // if blockSize is not explicitly set (px)
58
+ const hackHasExplicitBlock = blockSize.width !== measurements.width;
59
+
60
+ let debugData: any[] | null = null;
61
+ if (debug) {
62
+ debugData = [];
63
+ }
64
+
65
+ for (const word of measurements.words) {
66
+ for (const glyph of word.glyphs) {
67
+ let lineOffset = 0;
68
+ if (alignment === "center") {
69
+ lineOffset =
70
+ measurements.width * -0.5 -
71
+ (measurements.width - measurements.lineWidths[glyph.line]) * -0.5;
72
+ } else if (alignment === "right") {
73
+ const blockSizeEm = blockSize.width / em2px;
74
+
75
+ const delta = measurements.width - measurements.lineWidths[glyph.line];
76
+
77
+ lineOffset =
78
+ (hackHasExplicitBlock ? blockSizeEm / 2 : measurements.width / 2) -
79
+ measurements.width +
80
+ delta;
81
+ } else if (alignment === "left") {
82
+ const blockSizeEm = blockSize.width / em2px;
83
+
84
+ lineOffset = hackHasExplicitBlock
85
+ ? -blockSizeEm / 2
86
+ : -measurements.width / 2;
87
+ }
88
+
89
+ if (debug && debugData) {
90
+ debugData.push({
91
+ line: glyph.line,
92
+ word: word.glyphs.map((g) => g.char.char).join(""),
93
+ glyph: glyph.char.char,
94
+ startX: word.startX,
95
+ glyphX: glyph.offset[0],
96
+ advance: glyph.char.xadvance,
97
+ lineOffset,
98
+ startY: word.startY,
99
+ glyphY: glyph.offset[1],
100
+ });
101
+ }
102
+ textArray[offset] = word.startX + glyph.offset[0] + lineOffset;
103
+ textArray[offset + 1] = word.startY + glyph.offset[1];
104
+ textArray[offset + 2] = glyph.char.charIndex;
105
+
106
+ offset += 4;
107
+ }
108
+ }
109
+
110
+ if (debug && debugData) {
111
+ console.table(debugData);
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Measure the text and return measurements for block + each glyph.
117
+ * @param font - The font to use.
118
+ * @param text - The text to measure
119
+ * @param wordWrap - Maximum word length before word wrapping
120
+ * @returns The measurements of the text in em units.
121
+ */
122
+ export function measureText(
123
+ font: MsdfFont,
124
+ text: string,
125
+ wordWrap?: WordWrapOptions,
126
+ ): MsdfTextMeasurements {
127
+ let maxWidth = 0;
128
+ const lineWidths: number[] = [];
129
+
130
+ let textOffsetX = 0;
131
+ let textOffsetY = 0;
132
+ let line = 0;
133
+ let printedCharCount = 0;
134
+ let nextCharCode = text.charCodeAt(0);
135
+ let word: Word = { glyphs: [], width: 0, startX: 0, startY: 0 };
136
+
137
+ const words: Word[] = [];
138
+
139
+ for (let i = 0; i < text.length; i++) {
140
+ const isLastLetter = i === text.length - 1;
141
+
142
+ const charCode = nextCharCode;
143
+ nextCharCode = i < text.length - 1 ? text.charCodeAt(i + 1) : -1;
144
+
145
+ switch (charCode) {
146
+ case WhitespaceKeyCodes.HorizontalTab:
147
+ insertSpaces(TAB_SPACES);
148
+ break;
149
+ case WhitespaceKeyCodes.Newline:
150
+ flushLine();
151
+ flushWord();
152
+ break;
153
+ case WhitespaceKeyCodes.CarriageReturn:
154
+ break;
155
+ case WhitespaceKeyCodes.Space:
156
+ insertSpaces(1);
157
+ break;
158
+ default: {
159
+ const advance = font.getXAdvance(charCode, nextCharCode);
160
+ if (
161
+ wordWrap &&
162
+ wordWrap.breakOn === "character" &&
163
+ textOffsetX + advance > wordWrap.emWidth
164
+ ) {
165
+ if (word.startX === 0) {
166
+ flushWord();
167
+ } else {
168
+ lineWidths.push(textOffsetX - word.width);
169
+ line++;
170
+ maxWidth = Math.max(maxWidth, textOffsetX);
171
+ textOffsetX = word.width;
172
+ textOffsetY -= font.lineHeight;
173
+ word.startX = 0;
174
+ word.startY = textOffsetY;
175
+ word.glyphs.forEach((g) => {
176
+ g.line = line;
177
+ });
178
+ }
179
+ }
180
+ word.glyphs.push({
181
+ char: font.getChar(charCode),
182
+ offset: [word.width, 0],
183
+ line,
184
+ });
185
+
186
+ if (isLastLetter) {
187
+ flushWord();
188
+ }
189
+
190
+ word.width += advance;
191
+ textOffsetX += advance;
192
+ }
193
+ }
194
+ }
195
+
196
+ lineWidths.push(textOffsetX);
197
+ maxWidth = Math.max(maxWidth, textOffsetX);
198
+
199
+ const lineCount = lineWidths.length;
200
+
201
+ return {
202
+ width: maxWidth,
203
+ height: lineCount * font.lineHeight,
204
+ lineWidths,
205
+ lineCount,
206
+ printedCharCount,
207
+ words,
208
+ };
209
+
210
+ function flushWord() {
211
+ printedCharCount += word.glyphs.length;
212
+ words.push(word);
213
+ word = {
214
+ glyphs: [],
215
+ width: 0,
216
+ startX: textOffsetX,
217
+ startY: textOffsetY,
218
+ };
219
+ }
220
+
221
+ function flushLine() {
222
+ lineWidths.push(textOffsetX);
223
+ line++;
224
+ maxWidth = Math.max(maxWidth, textOffsetX);
225
+ textOffsetX = 0;
226
+ textOffsetY -= font.lineHeight;
227
+ }
228
+
229
+ function insertSpaces(spaces: number) {
230
+ if (spaces < 1) spaces = 1;
231
+ textOffsetX += font.getXAdvance(WhitespaceKeyCodes.Space) * spaces;
232
+ if (wordWrap?.breakOn === "word" && textOffsetX >= wordWrap.emWidth) {
233
+ flushLine();
234
+ }
235
+ flushWord();
236
+ }
237
+ }
238
+ export function findLargestFontSize(
239
+ font: MsdfFont,
240
+ text: string,
241
+ size: Size,
242
+ formatting: TextFormatting,
243
+ ): number | undefined {
244
+ if (!formatting.fontSize) {
245
+ throw new Error("fontSize is required for shrinkToFit");
246
+ }
247
+ if (!formatting.shrinkToFit) {
248
+ throw new Error("shrinkToFit is required for findLargestFontSize");
249
+ }
250
+ // Binary search to find largest font size that fits
251
+ const minSize = formatting.shrinkToFit.minFontSize;
252
+ const maxSize = formatting.shrinkToFit.maxFontSize ?? formatting.fontSize;
253
+ const maxLines = formatting.shrinkToFit.maxLines ?? Number.POSITIVE_INFINITY;
254
+
255
+ const threshold = 0.5;
256
+ let low = minSize;
257
+ let high = maxSize;
258
+
259
+ while (high - low > threshold) {
260
+ // Stop when we get close enough
261
+ const testSize = (low + high) / 2;
262
+ const testMeasure = measureText(font, text, formatting.wordWrap);
263
+
264
+ const padding = formatting.shrinkToFit.padding ?? 0;
265
+
266
+ const scaledWidth = testMeasure.width * (testSize / font.lineHeight);
267
+ const scaledHeight = testMeasure.height * (testSize / font.lineHeight);
268
+ const fitsWidth = scaledWidth <= size.width - size.width * padding;
269
+ const fitsHeight = scaledHeight <= size.height - size.height * padding;
270
+ const fitsLines = testMeasure.lineCount <= maxLines;
271
+
272
+ if (fitsWidth && fitsHeight && fitsLines) {
273
+ low = testSize;
274
+ } else {
275
+ high = testSize;
276
+ }
277
+ }
278
+
279
+ return low;
280
+ }
@@ -0,0 +1,149 @@
1
+ export default /*wgsl*/ `
2
+ // Adapted from: https://webgpu.github.io/webgpu-samples/?sample=textRenderingMsdf
3
+
4
+ // Quad vertex positions for a character
5
+ const pos = array(
6
+ vec2f(0, -1),
7
+ vec2f(1, -1),
8
+ vec2f(0, 0),
9
+ vec2f(1, 0),
10
+ );
11
+
12
+ // Debug colors for visualization
13
+ const debugColors = array(
14
+ vec4f(1, 0, 0, 1),
15
+ vec4f(0, 1, 0, 1),
16
+ vec4f(0, 0, 1, 1),
17
+ vec4f(1, 1, 1, 1),
18
+ );
19
+
20
+ // Vertex input from GPU
21
+ struct VertexInput {
22
+ @builtin(vertex_index) vertex: u32,
23
+ @builtin(instance_index) instance: u32,
24
+ };
25
+
26
+ // Output from vertex shader to fragment shader
27
+ struct VertexOutput {
28
+ @builtin(position) position: vec4f,
29
+ @location(0) texcoord: vec2f,
30
+ @location(1) debugColor: vec4f,
31
+ @location(2) @interpolate(flat) instanceIndex: u32,
32
+ };
33
+
34
+ // Metadata for a single character glyph
35
+ struct Char {
36
+ texOffset: vec2f, // Offset to top-left in MSDF texture (pixels)
37
+ texExtent: vec2f, // Size in texture (pixels)
38
+ size: vec2f, // Glyph size in ems
39
+ offset: vec2f, // Position offset in ems
40
+ };
41
+
42
+ // Metadata for a text block
43
+ struct TextBlockDescriptor {
44
+ transform: mat3x3f, // Text transform matrix (model matrix)
45
+ color: vec4f, // Text color
46
+ fontSize: f32, // Font size
47
+ blockWidth: f32, // Total width of text block
48
+ blockHeight: f32, // Total height of text block
49
+ bufferPosition: f32 // Index and length in textBuffer
50
+ };
51
+
52
+ // Font bindings
53
+ @group(0) @binding(0) var fontTexture: texture_2d<f32>;
54
+ @group(0) @binding(1) var fontSampler: sampler;
55
+ @group(0) @binding(2) var<storage> chars: array<Char>;
56
+ @group(0) @binding(3) var<uniform> fontData: vec4f; // Contains line height (x)
57
+
58
+ // Text bindings
59
+ @group(1) @binding(0) var<storage> texts: array<TextBlockDescriptor>;
60
+ @group(1) @binding(1) var<storage> textBuffer: array<vec4f>; // Each vec4: xy = glyph pos, z = char index
61
+
62
+ // Global uniforms
63
+ @group(2) @binding(0) var<uniform> viewProjectionMatrix: mat3x3f;
64
+
65
+ // Vertex shader
66
+ @vertex
67
+ fn vertexMain(input: VertexInput) -> VertexOutput {
68
+ // Because the instance index is used for character indexing, we are
69
+ // overloading the vertex index to store the instance of the text metadata.
70
+ //
71
+ // I.e...
72
+ // Vertex 0-4 = Instance 0, Vertex 0-4
73
+ // Vertex 4-8 = Instance 1, Vertex 0-4
74
+ // Vertex 8-12 = Instance 2, Vertex 0-4
75
+ let vertexIndex = input.vertex % 4;
76
+ let textIndex = input.vertex / 4;
77
+
78
+ let text = texts[textIndex];
79
+ let textElement = textBuffer[u32(text.bufferPosition) + input.instance];
80
+ let char = chars[u32(textElement.z)];
81
+
82
+ let lineHeight = fontData.x;
83
+ let textWidth = text.blockWidth;
84
+ let textHeight = text.blockHeight;
85
+
86
+ // Center text vertically; origin is mid-height
87
+ let offset = vec2f(0, -textHeight / 2);
88
+
89
+ // Glyph position in ems (quad pos * size + per-char offset)
90
+ let emPos = pos[vertexIndex] * char.size + char.offset + textElement.xy - offset;
91
+ let charPos = emPos * (text.fontSize / lineHeight);
92
+
93
+ var output: VertexOutput;
94
+ let transformedPosition = viewProjectionMatrix * text.transform * vec3f(charPos, 1);
95
+
96
+ output.position = vec4f(transformedPosition, 1);
97
+ output.texcoord = pos[vertexIndex] * vec2f(1, -1);
98
+ output.texcoord *= char.texExtent;
99
+ output.texcoord += char.texOffset;
100
+ output.debugColor = debugColors[vertexIndex];
101
+ output.instanceIndex = textIndex;
102
+ return output;
103
+
104
+ // To debug - hardcode quad in bottom right quarter of the screen:
105
+ // output.position = vec4f(pos[input.vertex], 0, 1);
106
+ }
107
+
108
+ // Signed distance function sampling for MSDF font rendering
109
+ fn sampleMsdf(texcoord: vec2f) -> f32 {
110
+ let c = textureSample(fontTexture, fontSampler, texcoord);
111
+ return max(min(c.r, c.g), min(max(c.r, c.g), c.b));
112
+ }
113
+
114
+ // Fragment shader
115
+ // Anti-aliasing technique by Paul Houx
116
+ // more details here:
117
+ // https://github.com/Chlumsky/msdfgen/issues/22#issuecomment-234958005
118
+ @fragment
119
+ fn fragmentMain(input: VertexOutput) -> @location(0) vec4f {
120
+ let text = texts[input.instanceIndex];
121
+
122
+ // pxRange (AKA distanceRange) comes from the msdfgen tool.
123
+ let pxRange = 4.0;
124
+ let texSize = vec2f(textureDimensions(fontTexture, 0));
125
+
126
+ let dx = texSize.x * length(vec2f(dpdxFine(input.texcoord.x), dpdyFine(input.texcoord.x)));
127
+ let dy = texSize.y * length(vec2f(dpdxFine(input.texcoord.y), dpdyFine(input.texcoord.y)));
128
+
129
+ let toPixels = pxRange * inverseSqrt(dx * dx + dy * dy);
130
+ let sigDist = sampleMsdf(input.texcoord) - 0.5;
131
+ let pxDist = sigDist * toPixels;
132
+
133
+ let edgeWidth = 0.5;
134
+ let alpha = smoothstep(-edgeWidth, edgeWidth, pxDist);
135
+
136
+ if (alpha < 0.001) {
137
+ discard;
138
+ }
139
+
140
+ let msdfColor = vec4f(text.color.rgb, text.color.a * alpha);
141
+ return msdfColor;
142
+
143
+ // Debug options:
144
+ // return text.color;
145
+ // return input.debugColor;
146
+ // return vec4f(1, 0, 1, 1); // hardcoded magenta
147
+ // return textureSample(fontTexture, fontSampler, input.texcoord);
148
+ }
149
+ `;