@mapwhit/tilerenderer 0.47.1

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 (356) hide show
  1. package/LICENSE.txt +87 -0
  2. package/README.md +25 -0
  3. package/build/min/.dir +0 -0
  4. package/build/min/package.json +3 -0
  5. package/build/min/src/shaders/_prelude.fragment.glsl.txt +13 -0
  6. package/build/min/src/shaders/_prelude.vertex.glsl.txt +14 -0
  7. package/build/min/src/shaders/background.fragment.glsl.txt +5 -0
  8. package/build/min/src/shaders/background.vertex.glsl.txt +1 -0
  9. package/build/min/src/shaders/background_pattern.fragment.glsl.txt +5 -0
  10. package/build/min/src/shaders/background_pattern.vertex.glsl.txt +1 -0
  11. package/build/min/src/shaders/circle.fragment.glsl.txt +20 -0
  12. package/build/min/src/shaders/circle.vertex.glsl.txt +17 -0
  13. package/build/min/src/shaders/clipping_mask.fragment.glsl.txt +1 -0
  14. package/build/min/src/shaders/clipping_mask.vertex.glsl.txt +1 -0
  15. package/build/min/src/shaders/collision_box.fragment.glsl.txt +1 -0
  16. package/build/min/src/shaders/collision_box.vertex.glsl.txt +1 -0
  17. package/build/min/src/shaders/collision_circle.fragment.glsl.txt +1 -0
  18. package/build/min/src/shaders/collision_circle.vertex.glsl.txt +1 -0
  19. package/build/min/src/shaders/debug.fragment.glsl.txt +1 -0
  20. package/build/min/src/shaders/debug.vertex.glsl.txt +1 -0
  21. package/build/min/src/shaders/fill.fragment.glsl.txt +10 -0
  22. package/build/min/src/shaders/fill.vertex.glsl.txt +7 -0
  23. package/build/min/src/shaders/fill_extrusion.fragment.glsl.txt +13 -0
  24. package/build/min/src/shaders/fill_extrusion.vertex.glsl.txt +9 -0
  25. package/build/min/src/shaders/fill_extrusion_pattern.fragment.glsl.txt +15 -0
  26. package/build/min/src/shaders/fill_extrusion_pattern.vertex.glsl.txt +11 -0
  27. package/build/min/src/shaders/fill_outline.fragment.glsl.txt +10 -0
  28. package/build/min/src/shaders/fill_outline.vertex.glsl.txt +7 -0
  29. package/build/min/src/shaders/fill_outline_pattern.fragment.glsl.txt +13 -0
  30. package/build/min/src/shaders/fill_outline_pattern.vertex.glsl.txt +9 -0
  31. package/build/min/src/shaders/fill_pattern.fragment.glsl.txt +13 -0
  32. package/build/min/src/shaders/fill_pattern.vertex.glsl.txt +9 -0
  33. package/build/min/src/shaders/heatmap.fragment.glsl.txt +10 -0
  34. package/build/min/src/shaders/heatmap.vertex.glsl.txt +8 -0
  35. package/build/min/src/shaders/heatmap_texture.fragment.glsl.txt +5 -0
  36. package/build/min/src/shaders/heatmap_texture.vertex.glsl.txt +1 -0
  37. package/build/min/src/shaders/hillshade.fragment.glsl.txt +7 -0
  38. package/build/min/src/shaders/hillshade.vertex.glsl.txt +1 -0
  39. package/build/min/src/shaders/hillshade_prepare.fragment.glsl.txt +8 -0
  40. package/build/min/src/shaders/hillshade_prepare.vertex.glsl.txt +1 -0
  41. package/build/min/src/shaders/line.fragment.glsl.txt +12 -0
  42. package/build/min/src/shaders/line.vertex.glsl.txt +17 -0
  43. package/build/min/src/shaders/line_gradient.fragment.glsl.txt +10 -0
  44. package/build/min/src/shaders/line_gradient.vertex.glsl.txt +16 -0
  45. package/build/min/src/shaders/line_pattern.fragment.glsl.txt +15 -0
  46. package/build/min/src/shaders/line_pattern.vertex.glsl.txt +20 -0
  47. package/build/min/src/shaders/line_sdf.fragment.glsl.txt +17 -0
  48. package/build/min/src/shaders/line_sdf.vertex.glsl.txt +20 -0
  49. package/build/min/src/shaders/raster.fragment.glsl.txt +5 -0
  50. package/build/min/src/shaders/raster.vertex.glsl.txt +1 -0
  51. package/build/min/src/shaders/symbol_icon.fragment.glsl.txt +9 -0
  52. package/build/min/src/shaders/symbol_icon.vertex.glsl.txt +5 -0
  53. package/build/min/src/shaders/symbol_sdf.fragment.glsl.txt +19 -0
  54. package/build/min/src/shaders/symbol_sdf.vertex.glsl.txt +13 -0
  55. package/package.json +44 -0
  56. package/src/css/mapbox-gl.css +506 -0
  57. package/src/css/svg/mapboxgl-ctrl-attrib.svg +3 -0
  58. package/src/css/svg/mapboxgl-ctrl-compass.svg +4 -0
  59. package/src/css/svg/mapboxgl-ctrl-fullscreen.svg +3 -0
  60. package/src/css/svg/mapboxgl-ctrl-geolocate-background.svg +3 -0
  61. package/src/css/svg/mapboxgl-ctrl-geolocate.svg +3 -0
  62. package/src/css/svg/mapboxgl-ctrl-logo-compact.svg +2 -0
  63. package/src/css/svg/mapboxgl-ctrl-logo.svg +1 -0
  64. package/src/css/svg/mapboxgl-ctrl-shrink.svg +3 -0
  65. package/src/css/svg/mapboxgl-ctrl-zoom-in.svg +3 -0
  66. package/src/css/svg/mapboxgl-ctrl-zoom-out.svg +3 -0
  67. package/src/data/array_types.js +1138 -0
  68. package/src/data/bucket/circle_attributes.js +5 -0
  69. package/src/data/bucket/circle_bucket.js +118 -0
  70. package/src/data/bucket/fill_attributes.js +5 -0
  71. package/src/data/bucket/fill_bucket.js +166 -0
  72. package/src/data/bucket/fill_extrusion_attributes.js +11 -0
  73. package/src/data/bucket/fill_extrusion_bucket.js +247 -0
  74. package/src/data/bucket/heatmap_bucket.js +12 -0
  75. package/src/data/bucket/line_attributes.js +11 -0
  76. package/src/data/bucket/line_bucket.js +625 -0
  77. package/src/data/bucket/pattern_attributes.js +9 -0
  78. package/src/data/bucket/pattern_bucket_features.js +44 -0
  79. package/src/data/bucket/symbol_attributes.js +95 -0
  80. package/src/data/bucket/symbol_bucket.js +697 -0
  81. package/src/data/bucket.js +53 -0
  82. package/src/data/dem_data.js +126 -0
  83. package/src/data/extent.js +17 -0
  84. package/src/data/feature_index.js +254 -0
  85. package/src/data/index_array_type.js +14 -0
  86. package/src/data/load_geometry.js +42 -0
  87. package/src/data/pos_attributes.js +3 -0
  88. package/src/data/program_configuration.js +782 -0
  89. package/src/data/raster_bounds_attributes.js +6 -0
  90. package/src/data/segment.js +63 -0
  91. package/src/geo/coordinate.js +78 -0
  92. package/src/geo/lng_lat.js +129 -0
  93. package/src/geo/lng_lat_bounds.js +253 -0
  94. package/src/geo/transform.js +605 -0
  95. package/src/gl/color_mode.js +21 -0
  96. package/src/gl/context.js +193 -0
  97. package/src/gl/cull_face_mode.js +22 -0
  98. package/src/gl/depth_mode.js +18 -0
  99. package/src/gl/framebuffer.js +28 -0
  100. package/src/gl/index_buffer.js +52 -0
  101. package/src/gl/stencil_mode.js +17 -0
  102. package/src/gl/types.js +0 -0
  103. package/src/gl/value.js +676 -0
  104. package/src/gl/vertex_buffer.js +101 -0
  105. package/src/index.js +50 -0
  106. package/src/render/draw_background.js +60 -0
  107. package/src/render/draw_circle.js +55 -0
  108. package/src/render/draw_collision_debug.js +45 -0
  109. package/src/render/draw_debug.js +429 -0
  110. package/src/render/draw_fill.js +143 -0
  111. package/src/render/draw_fill_extrusion.js +101 -0
  112. package/src/render/draw_heatmap.js +159 -0
  113. package/src/render/draw_hillshade.js +144 -0
  114. package/src/render/draw_line.js +99 -0
  115. package/src/render/draw_raster.js +151 -0
  116. package/src/render/draw_symbol.js +231 -0
  117. package/src/render/glyph_atlas.js +55 -0
  118. package/src/render/glyph_manager.js +145 -0
  119. package/src/render/image_atlas.js +97 -0
  120. package/src/render/image_manager.js +183 -0
  121. package/src/render/line_atlas.js +139 -0
  122. package/src/render/painter.js +483 -0
  123. package/src/render/program/background_program.js +46 -0
  124. package/src/render/program/circle_program.js +40 -0
  125. package/src/render/program/clipping_mask_program.js +11 -0
  126. package/src/render/program/collision_program.js +28 -0
  127. package/src/render/program/debug_program.js +13 -0
  128. package/src/render/program/fill_extrusion_program.js +76 -0
  129. package/src/render/program/fill_program.js +60 -0
  130. package/src/render/program/heatmap_program.js +46 -0
  131. package/src/render/program/hillshade_program.js +77 -0
  132. package/src/render/program/line_program.js +119 -0
  133. package/src/render/program/pattern.js +57 -0
  134. package/src/render/program/program_uniforms.js +46 -0
  135. package/src/render/program/raster_program.js +50 -0
  136. package/src/render/program/symbol_program.js +112 -0
  137. package/src/render/program.js +133 -0
  138. package/src/render/texture.js +88 -0
  139. package/src/render/tile_mask.js +108 -0
  140. package/src/render/uniform_binding.js +129 -0
  141. package/src/render/vertex_array_object.js +155 -0
  142. package/src/shaders/README.md +42 -0
  143. package/src/shaders/_prelude.fragment.glsl +17 -0
  144. package/src/shaders/_prelude.vertex.glsl +73 -0
  145. package/src/shaders/background.fragment.glsl +10 -0
  146. package/src/shaders/background.vertex.glsl +7 -0
  147. package/src/shaders/background_pattern.fragment.glsl +28 -0
  148. package/src/shaders/background_pattern.vertex.glsl +20 -0
  149. package/src/shaders/circle.fragment.glsl +39 -0
  150. package/src/shaders/circle.vertex.glsl +63 -0
  151. package/src/shaders/clipping_mask.fragment.glsl +3 -0
  152. package/src/shaders/clipping_mask.vertex.glsl +7 -0
  153. package/src/shaders/collision_box.fragment.glsl +21 -0
  154. package/src/shaders/collision_box.vertex.glsl +26 -0
  155. package/src/shaders/collision_circle.fragment.glsl +34 -0
  156. package/src/shaders/collision_circle.vertex.glsl +36 -0
  157. package/src/shaders/debug.fragment.glsl +5 -0
  158. package/src/shaders/debug.vertex.glsl +7 -0
  159. package/src/shaders/encode_attribute.js +19 -0
  160. package/src/shaders/fill.fragment.glsl +13 -0
  161. package/src/shaders/fill.vertex.glsl +13 -0
  162. package/src/shaders/fill_extrusion.fragment.glsl +16 -0
  163. package/src/shaders/fill_extrusion.vertex.glsl +66 -0
  164. package/src/shaders/fill_extrusion_pattern.fragment.glsl +41 -0
  165. package/src/shaders/fill_extrusion_pattern.vertex.glsl +76 -0
  166. package/src/shaders/fill_outline.fragment.glsl +17 -0
  167. package/src/shaders/fill_outline.vertex.glsl +17 -0
  168. package/src/shaders/fill_outline_pattern.fragment.glsl +43 -0
  169. package/src/shaders/fill_outline_pattern.vertex.glsl +41 -0
  170. package/src/shaders/fill_pattern.fragment.glsl +36 -0
  171. package/src/shaders/fill_pattern.vertex.glsl +36 -0
  172. package/src/shaders/heatmap.fragment.glsl +21 -0
  173. package/src/shaders/heatmap.vertex.glsl +53 -0
  174. package/src/shaders/heatmap_texture.fragment.glsl +14 -0
  175. package/src/shaders/heatmap_texture.vertex.glsl +11 -0
  176. package/src/shaders/hillshade.fragment.glsl +52 -0
  177. package/src/shaders/hillshade.vertex.glsl +11 -0
  178. package/src/shaders/hillshade_prepare.fragment.glsl +72 -0
  179. package/src/shaders/hillshade_prepare.vertex.glsl +15 -0
  180. package/src/shaders/index.js +194 -0
  181. package/src/shaders/line.fragment.glsl +28 -0
  182. package/src/shaders/line.vertex.glsl +84 -0
  183. package/src/shaders/line_gradient.fragment.glsl +34 -0
  184. package/src/shaders/line_gradient.vertex.glsl +84 -0
  185. package/src/shaders/line_pattern.fragment.glsl +69 -0
  186. package/src/shaders/line_pattern.vertex.glsl +88 -0
  187. package/src/shaders/line_sdf.fragment.glsl +44 -0
  188. package/src/shaders/line_sdf.vertex.glsl +95 -0
  189. package/src/shaders/raster.fragment.glsl +52 -0
  190. package/src/shaders/raster.vertex.glsl +21 -0
  191. package/src/shaders/symbol_icon.fragment.glsl +17 -0
  192. package/src/shaders/symbol_icon.vertex.glsl +91 -0
  193. package/src/shaders/symbol_sdf.fragment.glsl +50 -0
  194. package/src/shaders/symbol_sdf.vertex.glsl +117 -0
  195. package/src/source/geojson_source.js +267 -0
  196. package/src/source/geojson_worker_source.js +210 -0
  197. package/src/source/geojson_wrapper.js +67 -0
  198. package/src/source/image_source.js +213 -0
  199. package/src/source/load_tilejson.js +40 -0
  200. package/src/source/pixels_to_tile_units.js +17 -0
  201. package/src/source/query_features.js +198 -0
  202. package/src/source/raster_dem_tile_source.js +140 -0
  203. package/src/source/raster_dem_tile_worker_source.js +26 -0
  204. package/src/source/raster_tile_source.js +126 -0
  205. package/src/source/rtl_text_plugin.js +63 -0
  206. package/src/source/source.js +75 -0
  207. package/src/source/source_cache.js +794 -0
  208. package/src/source/source_state.js +55 -0
  209. package/src/source/tile.js +332 -0
  210. package/src/source/tile_bounds.js +40 -0
  211. package/src/source/tile_cache.js +122 -0
  212. package/src/source/tile_id.js +150 -0
  213. package/src/source/vector_tile_source.js +144 -0
  214. package/src/source/vector_tile_worker_source.js +126 -0
  215. package/src/source/worker.js +175 -0
  216. package/src/source/worker_source.js +14 -0
  217. package/src/source/worker_tile.js +199 -0
  218. package/src/style/create_style_layer.js +25 -0
  219. package/src/style/evaluation_parameters.js +45 -0
  220. package/src/style/light.js +112 -0
  221. package/src/style/load_glyph_range.js +17 -0
  222. package/src/style/load_sprite.js +26 -0
  223. package/src/style/parse_glyph_pbf.js +45 -0
  224. package/src/style/pauseable_placement.js +88 -0
  225. package/src/style/properties.js +691 -0
  226. package/src/style/query_utils.js +39 -0
  227. package/src/style/style.js +955 -0
  228. package/src/style/style_layer/background_style_layer.js +11 -0
  229. package/src/style/style_layer/background_style_layer_properties.js +25 -0
  230. package/src/style/style_layer/circle_style_layer.js +93 -0
  231. package/src/style/style_layer/circle_style_layer_properties.js +76 -0
  232. package/src/style/style_layer/fill_extrusion_style_layer.js +194 -0
  233. package/src/style/style_layer/fill_extrusion_style_layer_properties.js +56 -0
  234. package/src/style/style_layer/fill_style_layer.js +46 -0
  235. package/src/style/style_layer/fill_style_layer_properties.js +45 -0
  236. package/src/style/style_layer/heatmap_style_layer.js +51 -0
  237. package/src/style/style_layer/heatmap_style_layer_properties.js +52 -0
  238. package/src/style/style_layer/hillshade_style_layer.js +15 -0
  239. package/src/style/style_layer/hillshade_style_layer_properties.js +43 -0
  240. package/src/style/style_layer/line_style_layer.js +129 -0
  241. package/src/style/style_layer/line_style_layer_properties.js +104 -0
  242. package/src/style/style_layer/raster_style_layer.js +11 -0
  243. package/src/style/style_layer/raster_style_layer_properties.js +55 -0
  244. package/src/style/style_layer/symbol_style_layer.js +66 -0
  245. package/src/style/style_layer/symbol_style_layer_properties.js +288 -0
  246. package/src/style/style_layer.js +183 -0
  247. package/src/style/style_layer_index.js +61 -0
  248. package/src/style/zoom_history.js +36 -0
  249. package/src/style-spec/deref.js +51 -0
  250. package/src/style-spec/error/parsing_error.js +8 -0
  251. package/src/style-spec/error/validation_error.js +10 -0
  252. package/src/style-spec/expression/compound_expression.js +118 -0
  253. package/src/style-spec/expression/definitions/array.js +82 -0
  254. package/src/style-spec/expression/definitions/assertion.js +69 -0
  255. package/src/style-spec/expression/definitions/at.js +57 -0
  256. package/src/style-spec/expression/definitions/case.js +73 -0
  257. package/src/style-spec/expression/definitions/coalesce.js +68 -0
  258. package/src/style-spec/expression/definitions/coercion.js +96 -0
  259. package/src/style-spec/expression/definitions/collator.js +102 -0
  260. package/src/style-spec/expression/definitions/equals.js +93 -0
  261. package/src/style-spec/expression/definitions/index.js +407 -0
  262. package/src/style-spec/expression/definitions/interpolate.js +235 -0
  263. package/src/style-spec/expression/definitions/length.js +54 -0
  264. package/src/style-spec/expression/definitions/let.js +60 -0
  265. package/src/style-spec/expression/definitions/literal.js +64 -0
  266. package/src/style-spec/expression/definitions/match.js +142 -0
  267. package/src/style-spec/expression/definitions/step.js +116 -0
  268. package/src/style-spec/expression/definitions/var.js +38 -0
  269. package/src/style-spec/expression/evaluation_context.js +35 -0
  270. package/src/style-spec/expression/index.js +329 -0
  271. package/src/style-spec/expression/is_constant.js +63 -0
  272. package/src/style-spec/expression/parsing_context.js +213 -0
  273. package/src/style-spec/expression/parsing_error.js +9 -0
  274. package/src/style-spec/expression/runtime_error.js +12 -0
  275. package/src/style-spec/expression/scope.js +34 -0
  276. package/src/style-spec/expression/stops.js +37 -0
  277. package/src/style-spec/expression/types.js +77 -0
  278. package/src/style-spec/expression/values.js +126 -0
  279. package/src/style-spec/feature_filter/README.md +55 -0
  280. package/src/style-spec/feature_filter/index.js +158 -0
  281. package/src/style-spec/function/convert.js +256 -0
  282. package/src/style-spec/function/index.js +299 -0
  283. package/src/style-spec/group_by_layout.js +68 -0
  284. package/src/style-spec/reference/v8.json +5356 -0
  285. package/src/style-spec/util/color.js +73 -0
  286. package/src/style-spec/util/color_spaces.js +128 -0
  287. package/src/style-spec/util/eval_support.js +8 -0
  288. package/src/style-spec/util/get_type.js +18 -0
  289. package/src/style-spec/util/interpolate.js +21 -0
  290. package/src/style-spec/util/properties.js +17 -0
  291. package/src/style-spec/util/ref_properties.js +1 -0
  292. package/src/style-spec/util/result.js +19 -0
  293. package/src/symbol/anchor.js +21 -0
  294. package/src/symbol/check_max_angle.js +75 -0
  295. package/src/symbol/clip_line.js +73 -0
  296. package/src/symbol/collision_feature.js +230 -0
  297. package/src/symbol/collision_index.js +379 -0
  298. package/src/symbol/cross_tile_symbol_index.js +270 -0
  299. package/src/symbol/get_anchors.js +177 -0
  300. package/src/symbol/grid_index.js +318 -0
  301. package/src/symbol/mergelines.js +75 -0
  302. package/src/symbol/opacity_state.js +21 -0
  303. package/src/symbol/placement.js +563 -0
  304. package/src/symbol/projection.js +601 -0
  305. package/src/symbol/quads.js +173 -0
  306. package/src/symbol/shaping.js +347 -0
  307. package/src/symbol/symbol_layout.js +519 -0
  308. package/src/symbol/symbol_size.js +110 -0
  309. package/src/symbol/transform_text.js +16 -0
  310. package/src/ui/anchor.js +24 -0
  311. package/src/ui/bind_handlers.js +199 -0
  312. package/src/ui/camera.js +954 -0
  313. package/src/ui/events.js +210 -0
  314. package/src/ui/handler/box_zoom.js +151 -0
  315. package/src/ui/handler/dblclick_zoom.js +91 -0
  316. package/src/ui/handler/drag_pan.js +285 -0
  317. package/src/ui/handler/drag_rotate.js +290 -0
  318. package/src/ui/handler/frame.js +28 -0
  319. package/src/ui/handler/inertia.js +45 -0
  320. package/src/ui/handler/keyboard.js +148 -0
  321. package/src/ui/handler/scroll_zoom.js +284 -0
  322. package/src/ui/handler/touch_zoom_rotate.js +263 -0
  323. package/src/ui/map.js +1645 -0
  324. package/src/util/actor.js +104 -0
  325. package/src/util/async.js +23 -0
  326. package/src/util/browser.js +61 -0
  327. package/src/util/callback.js +26 -0
  328. package/src/util/classify_rings.js +43 -0
  329. package/src/util/color_ramp.js +24 -0
  330. package/src/util/config.js +24 -0
  331. package/src/util/dictionary_coder.js +25 -0
  332. package/src/util/dispatcher.js +68 -0
  333. package/src/util/dom.js +102 -0
  334. package/src/util/evented.js +182 -0
  335. package/src/util/find_pole_of_inaccessibility.js +129 -0
  336. package/src/util/global_worker_pool.js +15 -0
  337. package/src/util/image.js +124 -0
  338. package/src/util/interpolate.js +5 -0
  339. package/src/util/intersection_tests.js +207 -0
  340. package/src/util/is_char_in_unicode_block.js +287 -0
  341. package/src/util/loader/image.js +32 -0
  342. package/src/util/object.js +178 -0
  343. package/src/util/script_detection.js +337 -0
  344. package/src/util/struct_array.js +197 -0
  345. package/src/util/task_queue.js +57 -0
  346. package/src/util/throttle.js +26 -0
  347. package/src/util/tile_cover.js +114 -0
  348. package/src/util/token.js +13 -0
  349. package/src/util/unique_id.js +12 -0
  350. package/src/util/util.js +192 -0
  351. package/src/util/vectortile_to_geojson.js +44 -0
  352. package/src/util/verticalize_punctuation.js +112 -0
  353. package/src/util/warn.js +21 -0
  354. package/src/util/web_worker.js +5 -0
  355. package/src/util/web_worker_transfer.js +228 -0
  356. package/src/util/worker_pool.js +41 -0
@@ -0,0 +1,601 @@
1
+ const Point = require('@mapbox/point-geometry');
2
+
3
+ const { mat4, vec4 } = require('@mapbox/gl-matrix');
4
+ const symbolSize = require('./symbol_size');
5
+ const { addDynamicAttributes } = require('../data/bucket/symbol_bucket');
6
+ const properties = require('../style/style_layer/symbol_style_layer_properties');
7
+ const symbolLayoutProperties = properties.layout;
8
+
9
+ const { WritingMode } = require('../symbol/shaping');
10
+
11
+ module.exports = {
12
+ updateLineLabels,
13
+ getLabelPlaneMatrix,
14
+ getGlCoordMatrix,
15
+ project,
16
+ placeFirstAndLastGlyph,
17
+ xyTransformMat4
18
+ };
19
+
20
+ /*
21
+ * # Overview of coordinate spaces
22
+ *
23
+ * ## Tile coordinate spaces
24
+ * Each label has an anchor. Some labels have corresponding line geometries.
25
+ * The points for both anchors and lines are stored in tile units. Each tile has it's own
26
+ * coordinate space going from (0, 0) at the top left to (EXTENT, EXTENT) at the bottom right.
27
+ *
28
+ * ## GL coordinate space
29
+ * At the end of everything, the vertex shader needs to produce a position in GL coordinate space,
30
+ * which is (-1, 1) at the top left and (1, -1) in the bottom right.
31
+ *
32
+ * ## Map pixel coordinate spaces
33
+ * Each tile has a pixel coordinate space. It's just the tile units scaled so that one unit is
34
+ * whatever counts as 1 pixel at the current zoom.
35
+ * This space is used for pitch-alignment=map, rotation-alignment=map
36
+ *
37
+ * ## Rotated map pixel coordinate spaces
38
+ * Like the above, but rotated so axis of the space are aligned with the viewport instead of the tile.
39
+ * This space is used for pitch-alignment=map, rotation-alignment=viewport
40
+ *
41
+ * ## Viewport pixel coordinate space
42
+ * (0, 0) is at the top left of the canvas and (pixelWidth, pixelHeight) is at the bottom right corner
43
+ * of the canvas. This space is used for pitch-alignment=viewport
44
+ *
45
+ *
46
+ * # Vertex projection
47
+ * It goes roughly like this:
48
+ * 1. project the anchor and line from tile units into the correct label coordinate space
49
+ * - map pixel space pitch-alignment=map rotation-alignment=map
50
+ * - rotated map pixel space pitch-alignment=map rotation-alignment=viewport
51
+ * - viewport pixel space pitch-alignment=viewport rotation-alignment=*
52
+ * 2. if the label follows a line, find the point along the line that is the correct distance from the anchor.
53
+ * 3. add the glyph's corner offset to the point from step 3
54
+ * 4. convert from the label coordinate space to gl coordinates
55
+ *
56
+ * For horizontal labels we want to do step 1 in the shader for performance reasons (no cpu work).
57
+ * This is what `u_label_plane_matrix` is used for.
58
+ * For labels aligned with lines we have to steps 1 and 2 on the cpu since we need access to the line geometry.
59
+ * This is what `updateLineLabels(...)` does.
60
+ * Since the conversion is handled on the cpu we just set `u_label_plane_matrix` to an identity matrix.
61
+ *
62
+ * Steps 3 and 4 are done in the shaders for all labels.
63
+ */
64
+
65
+ /*
66
+ * Returns a matrix for converting from tile units to the correct label coordinate space.
67
+ */
68
+ function getLabelPlaneMatrix(posMatrix, pitchWithMap, rotateWithMap, transform, pixelsToTileUnits) {
69
+ const m = mat4.identity(new Float32Array(16));
70
+ if (pitchWithMap) {
71
+ mat4.identity(m);
72
+ mat4.scale(m, m, [1 / pixelsToTileUnits, 1 / pixelsToTileUnits, 1]);
73
+ if (!rotateWithMap) {
74
+ mat4.rotateZ(m, m, transform.angle);
75
+ }
76
+ } else {
77
+ mat4.scale(m, m, [transform.width / 2, -transform.height / 2, 1]);
78
+ mat4.translate(m, m, [1, -1, 0]);
79
+ mat4.multiply(m, m, posMatrix);
80
+ }
81
+ return m;
82
+ }
83
+
84
+ /*
85
+ * Returns a matrix for converting from the correct label coordinate space to gl coords.
86
+ */
87
+ function getGlCoordMatrix(posMatrix, pitchWithMap, rotateWithMap, transform, pixelsToTileUnits) {
88
+ const m = mat4.identity(new Float32Array(16));
89
+ if (pitchWithMap) {
90
+ mat4.multiply(m, m, posMatrix);
91
+ mat4.scale(m, m, [pixelsToTileUnits, pixelsToTileUnits, 1]);
92
+ if (!rotateWithMap) {
93
+ mat4.rotateZ(m, m, -transform.angle);
94
+ }
95
+ } else {
96
+ mat4.scale(m, m, [1, -1, 1]);
97
+ mat4.translate(m, m, [-1, -1, 0]);
98
+ mat4.scale(m, m, [2 / transform.width, 2 / transform.height, 1]);
99
+ }
100
+ return m;
101
+ }
102
+
103
+ function project(point, matrix) {
104
+ const pos = [point.x, point.y, 0, 1];
105
+ xyTransformMat4(pos, pos, matrix);
106
+ const w = pos[3];
107
+ return {
108
+ point: new Point(pos[0] / w, pos[1] / w),
109
+ signedDistanceFromCamera: w
110
+ };
111
+ }
112
+
113
+ function isVisible(anchorPos, clippingBuffer) {
114
+ const x = anchorPos[0] / anchorPos[3];
115
+ const y = anchorPos[1] / anchorPos[3];
116
+ const inPaddedViewport =
117
+ x >= -clippingBuffer[0] && x <= clippingBuffer[0] && y >= -clippingBuffer[1] && y <= clippingBuffer[1];
118
+ return inPaddedViewport;
119
+ }
120
+
121
+ /*
122
+ * Update the `dynamicLayoutVertexBuffer` for the buffer with the correct glyph positions for the current map view.
123
+ * This is only run on labels that are aligned with lines. Horizontal labels are handled entirely in the shader.
124
+ */
125
+ function updateLineLabels(
126
+ bucket,
127
+ posMatrix,
128
+ painter,
129
+ isText,
130
+ labelPlaneMatrix,
131
+ glCoordMatrix,
132
+ pitchWithMap,
133
+ keepUpright
134
+ ) {
135
+ const sizeData = isText ? bucket.textSizeData : bucket.iconSizeData;
136
+ const partiallyEvaluatedSize = symbolSize.evaluateSizeForZoom(
137
+ sizeData,
138
+ painter.transform.zoom,
139
+ symbolLayoutProperties.properties[isText ? 'text-size' : 'icon-size']
140
+ );
141
+
142
+ const clippingBuffer = [(256 / painter.width) * 2 + 1, (256 / painter.height) * 2 + 1];
143
+
144
+ const dynamicLayoutVertexArray = isText ? bucket.text.dynamicLayoutVertexArray : bucket.icon.dynamicLayoutVertexArray;
145
+ dynamicLayoutVertexArray.clear();
146
+
147
+ const lineVertexArray = bucket.lineVertexArray;
148
+ const placedSymbols = isText ? bucket.text.placedSymbolArray : bucket.icon.placedSymbolArray;
149
+
150
+ const aspectRatio = painter.transform.width / painter.transform.height;
151
+
152
+ let useVertical = false;
153
+
154
+ for (let s = 0; s < placedSymbols.length; s++) {
155
+ const symbol = placedSymbols.get(s);
156
+ // Don't do calculations for vertical glyphs unless the previous symbol was horizontal
157
+ // and we determined that vertical glyphs were necessary.
158
+ // Also don't do calculations for symbols that are collided and fully faded out
159
+ if (symbol.hidden || (symbol.writingMode === WritingMode.vertical && !useVertical)) {
160
+ hideGlyphs(symbol.numGlyphs, dynamicLayoutVertexArray);
161
+ continue;
162
+ }
163
+ // Awkward... but we're counting on the paired "vertical" symbol coming immediately after its horizontal counterpart
164
+ useVertical = false;
165
+
166
+ const anchorPos = [symbol.anchorX, symbol.anchorY, 0, 1];
167
+ vec4.transformMat4(anchorPos, anchorPos, posMatrix);
168
+
169
+ // Don't bother calculating the correct point for invisible labels.
170
+ if (!isVisible(anchorPos, clippingBuffer)) {
171
+ hideGlyphs(symbol.numGlyphs, dynamicLayoutVertexArray);
172
+ continue;
173
+ }
174
+
175
+ const cameraToAnchorDistance = anchorPos[3];
176
+ const perspectiveRatio = 0.5 + 0.5 * (cameraToAnchorDistance / painter.transform.cameraToCenterDistance);
177
+
178
+ const fontSize = symbolSize.evaluateSizeForFeature(sizeData, partiallyEvaluatedSize, symbol);
179
+ const pitchScaledFontSize = pitchWithMap ? fontSize * perspectiveRatio : fontSize / perspectiveRatio;
180
+
181
+ const tileAnchorPoint = new Point(symbol.anchorX, symbol.anchorY);
182
+ const anchorPoint = project(tileAnchorPoint, labelPlaneMatrix).point;
183
+ const projectionCache = {};
184
+
185
+ const placeUnflipped = placeGlyphsAlongLine(
186
+ symbol,
187
+ pitchScaledFontSize,
188
+ false /*unflipped*/,
189
+ keepUpright,
190
+ posMatrix,
191
+ labelPlaneMatrix,
192
+ glCoordMatrix,
193
+ bucket.glyphOffsetArray,
194
+ lineVertexArray,
195
+ dynamicLayoutVertexArray,
196
+ anchorPoint,
197
+ tileAnchorPoint,
198
+ projectionCache,
199
+ aspectRatio
200
+ );
201
+
202
+ useVertical = placeUnflipped.useVertical;
203
+
204
+ if (
205
+ placeUnflipped.notEnoughRoom ||
206
+ useVertical ||
207
+ (placeUnflipped.needsFlipping &&
208
+ placeGlyphsAlongLine(
209
+ symbol,
210
+ pitchScaledFontSize,
211
+ true /*flipped*/,
212
+ keepUpright,
213
+ posMatrix,
214
+ labelPlaneMatrix,
215
+ glCoordMatrix,
216
+ bucket.glyphOffsetArray,
217
+ lineVertexArray,
218
+ dynamicLayoutVertexArray,
219
+ anchorPoint,
220
+ tileAnchorPoint,
221
+ projectionCache,
222
+ aspectRatio
223
+ ).notEnoughRoom)
224
+ ) {
225
+ hideGlyphs(symbol.numGlyphs, dynamicLayoutVertexArray);
226
+ }
227
+ }
228
+
229
+ if (isText) {
230
+ bucket.text.dynamicLayoutVertexBuffer.updateData(dynamicLayoutVertexArray);
231
+ } else {
232
+ bucket.icon.dynamicLayoutVertexBuffer.updateData(dynamicLayoutVertexArray);
233
+ }
234
+ }
235
+
236
+ function placeFirstAndLastGlyph(
237
+ fontScale,
238
+ glyphOffsetArray,
239
+ lineOffsetX,
240
+ lineOffsetY,
241
+ flip,
242
+ anchorPoint,
243
+ tileAnchorPoint,
244
+ symbol,
245
+ lineVertexArray,
246
+ labelPlaneMatrix,
247
+ projectionCache,
248
+ returnTileDistance
249
+ ) {
250
+ const glyphEndIndex = symbol.glyphStartIndex + symbol.numGlyphs;
251
+ const lineStartIndex = symbol.lineStartIndex;
252
+ const lineEndIndex = symbol.lineStartIndex + symbol.lineLength;
253
+
254
+ const firstGlyphOffset = glyphOffsetArray.getoffsetX(symbol.glyphStartIndex);
255
+ const lastGlyphOffset = glyphOffsetArray.getoffsetX(glyphEndIndex - 1);
256
+
257
+ const firstPlacedGlyph = placeGlyphAlongLine(
258
+ fontScale * firstGlyphOffset,
259
+ lineOffsetX,
260
+ lineOffsetY,
261
+ flip,
262
+ anchorPoint,
263
+ tileAnchorPoint,
264
+ symbol.segment,
265
+ lineStartIndex,
266
+ lineEndIndex,
267
+ lineVertexArray,
268
+ labelPlaneMatrix,
269
+ projectionCache,
270
+ returnTileDistance
271
+ );
272
+ if (!firstPlacedGlyph) return null;
273
+
274
+ const lastPlacedGlyph = placeGlyphAlongLine(
275
+ fontScale * lastGlyphOffset,
276
+ lineOffsetX,
277
+ lineOffsetY,
278
+ flip,
279
+ anchorPoint,
280
+ tileAnchorPoint,
281
+ symbol.segment,
282
+ lineStartIndex,
283
+ lineEndIndex,
284
+ lineVertexArray,
285
+ labelPlaneMatrix,
286
+ projectionCache,
287
+ returnTileDistance
288
+ );
289
+ if (!lastPlacedGlyph) return null;
290
+
291
+ return { first: firstPlacedGlyph, last: lastPlacedGlyph };
292
+ }
293
+
294
+ function requiresOrientationChange(writingMode, firstPoint, lastPoint, aspectRatio) {
295
+ if (writingMode === WritingMode.horizontal) {
296
+ // On top of choosing whether to flip, choose whether to render this version of the glyphs or the alternate
297
+ // vertical glyphs. We can't just filter out vertical glyphs in the horizontal range because the horizontal
298
+ // and vertical versions can have slightly different projections which could lead to angles where both or
299
+ // neither showed.
300
+ const rise = Math.abs(lastPoint.y - firstPoint.y);
301
+ const run = Math.abs(lastPoint.x - firstPoint.x) * aspectRatio;
302
+ if (rise > run) {
303
+ return { useVertical: true };
304
+ }
305
+ }
306
+
307
+ if (writingMode === WritingMode.vertical ? firstPoint.y < lastPoint.y : firstPoint.x > lastPoint.x) {
308
+ // Includes "horizontalOnly" case for labels without vertical glyphs
309
+ return { needsFlipping: true };
310
+ }
311
+
312
+ return null;
313
+ }
314
+
315
+ function placeGlyphsAlongLine(
316
+ symbol,
317
+ fontSize,
318
+ flip,
319
+ keepUpright,
320
+ posMatrix,
321
+ labelPlaneMatrix,
322
+ glCoordMatrix,
323
+ glyphOffsetArray,
324
+ lineVertexArray,
325
+ dynamicLayoutVertexArray,
326
+ anchorPoint,
327
+ tileAnchorPoint,
328
+ projectionCache,
329
+ aspectRatio
330
+ ) {
331
+ const fontScale = fontSize / 24;
332
+ const lineOffsetX = symbol.lineOffsetX * fontSize;
333
+ const lineOffsetY = symbol.lineOffsetY * fontSize;
334
+
335
+ let placedGlyphs;
336
+ if (symbol.numGlyphs > 1) {
337
+ const glyphEndIndex = symbol.glyphStartIndex + symbol.numGlyphs;
338
+ const lineStartIndex = symbol.lineStartIndex;
339
+ const lineEndIndex = symbol.lineStartIndex + symbol.lineLength;
340
+
341
+ // Place the first and the last glyph in the label first, so we can figure out
342
+ // the overall orientation of the label and determine whether it needs to be flipped in keepUpright mode
343
+ const firstAndLastGlyph = placeFirstAndLastGlyph(
344
+ fontScale,
345
+ glyphOffsetArray,
346
+ lineOffsetX,
347
+ lineOffsetY,
348
+ flip,
349
+ anchorPoint,
350
+ tileAnchorPoint,
351
+ symbol,
352
+ lineVertexArray,
353
+ labelPlaneMatrix,
354
+ projectionCache,
355
+ false
356
+ );
357
+ if (!firstAndLastGlyph) {
358
+ return { notEnoughRoom: true };
359
+ }
360
+ const firstPoint = project(firstAndLastGlyph.first.point, glCoordMatrix).point;
361
+ const lastPoint = project(firstAndLastGlyph.last.point, glCoordMatrix).point;
362
+
363
+ if (keepUpright && !flip) {
364
+ const orientationChange = requiresOrientationChange(symbol.writingMode, firstPoint, lastPoint, aspectRatio);
365
+ if (orientationChange) {
366
+ return orientationChange;
367
+ }
368
+ }
369
+
370
+ placedGlyphs = [firstAndLastGlyph.first];
371
+ for (let glyphIndex = symbol.glyphStartIndex + 1; glyphIndex < glyphEndIndex - 1; glyphIndex++) {
372
+ // Since first and last glyph fit on the line, we're sure that the rest of the glyphs can be placed
373
+ // $FlowFixMe
374
+ placedGlyphs.push(
375
+ placeGlyphAlongLine(
376
+ fontScale * glyphOffsetArray.getoffsetX(glyphIndex),
377
+ lineOffsetX,
378
+ lineOffsetY,
379
+ flip,
380
+ anchorPoint,
381
+ tileAnchorPoint,
382
+ symbol.segment,
383
+ lineStartIndex,
384
+ lineEndIndex,
385
+ lineVertexArray,
386
+ labelPlaneMatrix,
387
+ projectionCache,
388
+ false
389
+ )
390
+ );
391
+ }
392
+ placedGlyphs.push(firstAndLastGlyph.last);
393
+ } else {
394
+ // Only a single glyph to place
395
+ // So, determine whether to flip based on projected angle of the line segment it's on
396
+ if (keepUpright && !flip) {
397
+ const a = project(tileAnchorPoint, posMatrix).point;
398
+ const tileVertexIndex = symbol.lineStartIndex + symbol.segment + 1;
399
+ // $FlowFixMe
400
+ const tileSegmentEnd = new Point(lineVertexArray.getx(tileVertexIndex), lineVertexArray.gety(tileVertexIndex));
401
+ const projectedVertex = project(tileSegmentEnd, posMatrix);
402
+ // We know the anchor will be in the viewport, but the end of the line segment may be
403
+ // behind the plane of the camera, in which case we can use a point at any arbitrary (closer)
404
+ // point on the segment.
405
+ const b =
406
+ projectedVertex.signedDistanceFromCamera > 0
407
+ ? projectedVertex.point
408
+ : projectTruncatedLineSegment(tileAnchorPoint, tileSegmentEnd, a, 1, posMatrix);
409
+
410
+ const orientationChange = requiresOrientationChange(symbol.writingMode, a, b, aspectRatio);
411
+ if (orientationChange) {
412
+ return orientationChange;
413
+ }
414
+ }
415
+ // $FlowFixMe
416
+ const singleGlyph = placeGlyphAlongLine(
417
+ fontScale * glyphOffsetArray.getoffsetX(symbol.glyphStartIndex),
418
+ lineOffsetX,
419
+ lineOffsetY,
420
+ flip,
421
+ anchorPoint,
422
+ tileAnchorPoint,
423
+ symbol.segment,
424
+ symbol.lineStartIndex,
425
+ symbol.lineStartIndex + symbol.lineLength,
426
+ lineVertexArray,
427
+ labelPlaneMatrix,
428
+ projectionCache,
429
+ false
430
+ );
431
+ if (!singleGlyph) return { notEnoughRoom: true };
432
+
433
+ placedGlyphs = [singleGlyph];
434
+ }
435
+
436
+ for (const glyph of placedGlyphs) {
437
+ addDynamicAttributes(dynamicLayoutVertexArray, glyph.point, glyph.angle);
438
+ }
439
+ return {};
440
+ }
441
+
442
+ function projectTruncatedLineSegment(
443
+ previousTilePoint,
444
+ currentTilePoint,
445
+ previousProjectedPoint,
446
+ minimumLength,
447
+ projectionMatrix
448
+ ) {
449
+ // We are assuming "previousTilePoint" won't project to a point within one unit of the camera plane
450
+ // If it did, that would mean our label extended all the way out from within the viewport to a (very distant)
451
+ // point near the plane of the camera. We wouldn't be able to render the label anyway once it crossed the
452
+ // plane of the camera.
453
+ const projectedUnitVertex = project(
454
+ previousTilePoint.add(previousTilePoint.sub(currentTilePoint)._unit()),
455
+ projectionMatrix
456
+ ).point;
457
+ const projectedUnitSegment = previousProjectedPoint.sub(projectedUnitVertex);
458
+
459
+ return previousProjectedPoint.add(projectedUnitSegment._mult(minimumLength / projectedUnitSegment.mag()));
460
+ }
461
+
462
+ function placeGlyphAlongLine(
463
+ offsetX,
464
+ lineOffsetX,
465
+ lineOffsetY,
466
+ flip,
467
+ anchorPoint,
468
+ tileAnchorPoint,
469
+ anchorSegment,
470
+ lineStartIndex,
471
+ lineEndIndex,
472
+ lineVertexArray,
473
+ labelPlaneMatrix,
474
+ projectionCache,
475
+ returnTileDistance
476
+ ) {
477
+ const combinedOffsetX = flip ? offsetX - lineOffsetX : offsetX + lineOffsetX;
478
+
479
+ let dir = combinedOffsetX > 0 ? 1 : -1;
480
+
481
+ let angle = 0;
482
+ if (flip) {
483
+ // The label needs to be flipped to keep text upright.
484
+ // Iterate in the reverse direction.
485
+ dir *= -1;
486
+ angle = Math.PI;
487
+ }
488
+
489
+ if (dir < 0) angle += Math.PI;
490
+
491
+ let currentIndex = dir > 0 ? lineStartIndex + anchorSegment : lineStartIndex + anchorSegment + 1;
492
+
493
+ const initialIndex = currentIndex;
494
+ let current = anchorPoint;
495
+ let prev = anchorPoint;
496
+ let distanceToPrev = 0;
497
+ let currentSegmentDistance = 0;
498
+ const absOffsetX = Math.abs(combinedOffsetX);
499
+
500
+ while (distanceToPrev + currentSegmentDistance <= absOffsetX) {
501
+ currentIndex += dir;
502
+
503
+ // offset does not fit on the projected line
504
+ if (currentIndex < lineStartIndex || currentIndex >= lineEndIndex) return null;
505
+
506
+ prev = current;
507
+
508
+ current = projectionCache[currentIndex];
509
+ if (current === undefined) {
510
+ const currentVertex = new Point(lineVertexArray.getx(currentIndex), lineVertexArray.gety(currentIndex));
511
+ const projection = project(currentVertex, labelPlaneMatrix);
512
+ if (projection.signedDistanceFromCamera > 0) {
513
+ current = projectionCache[currentIndex] = projection.point;
514
+ } else {
515
+ // The vertex is behind the plane of the camera, so we can't project it
516
+ // Instead, we'll create a vertex along the line that's far enough to include the glyph
517
+ const previousLineVertexIndex = currentIndex - dir;
518
+ const previousTilePoint =
519
+ distanceToPrev === 0
520
+ ? tileAnchorPoint
521
+ : new Point(lineVertexArray.getx(previousLineVertexIndex), lineVertexArray.gety(previousLineVertexIndex));
522
+ // Don't cache because the new vertex might not be far enough out for future glyphs on the same segment
523
+ current = projectTruncatedLineSegment(
524
+ previousTilePoint,
525
+ currentVertex,
526
+ prev,
527
+ absOffsetX - distanceToPrev + 1,
528
+ labelPlaneMatrix
529
+ );
530
+ }
531
+ }
532
+
533
+ distanceToPrev += currentSegmentDistance;
534
+ currentSegmentDistance = prev.dist(current);
535
+ }
536
+
537
+ // The point is on the current segment. Interpolate to find it.
538
+ const segmentInterpolationT = (absOffsetX - distanceToPrev) / currentSegmentDistance;
539
+ const prevToCurrent = current.sub(prev);
540
+ const p = prevToCurrent.mult(segmentInterpolationT)._add(prev);
541
+
542
+ // offset the point from the line to text-offset and icon-offset
543
+ p._add(
544
+ prevToCurrent
545
+ ._unit()
546
+ ._perp()
547
+ ._mult(lineOffsetY * dir)
548
+ );
549
+
550
+ const segmentAngle = angle + Math.atan2(current.y - prev.y, current.x - prev.x);
551
+
552
+ return {
553
+ point: p,
554
+ angle: segmentAngle,
555
+ tileDistance: returnTileDistance
556
+ ? {
557
+ prevTileDistance:
558
+ currentIndex - dir === initialIndex ? 0 : lineVertexArray.gettileUnitDistanceFromAnchor(currentIndex - dir),
559
+ lastSegmentViewportDistance: absOffsetX - distanceToPrev
560
+ }
561
+ : null
562
+ };
563
+ }
564
+
565
+ const hiddenGlyphAttributes = new Float32Array([
566
+ Number.NEGATIVE_INFINITY,
567
+ Number.NEGATIVE_INFINITY,
568
+ 0,
569
+ Number.NEGATIVE_INFINITY,
570
+ Number.NEGATIVE_INFINITY,
571
+ 0,
572
+ Number.NEGATIVE_INFINITY,
573
+ Number.NEGATIVE_INFINITY,
574
+ 0,
575
+ Number.NEGATIVE_INFINITY,
576
+ Number.NEGATIVE_INFINITY,
577
+ 0
578
+ ]);
579
+
580
+ // Hide them by moving them offscreen. We still need to add them to the buffer
581
+ // because the dynamic buffer is paired with a static buffer that doesn't get updated.
582
+ function hideGlyphs(num, dynamicLayoutVertexArray) {
583
+ for (let i = 0; i < num; i++) {
584
+ const offset = dynamicLayoutVertexArray.length;
585
+ dynamicLayoutVertexArray.resize(offset + 4);
586
+ // Since all hidden glyphs have the same attributes, we can build up the array faster with a single call to Float32Array.set
587
+ // for each set of four vertices, instead of calling addDynamicAttributes for each vertex.
588
+ dynamicLayoutVertexArray.float32.set(hiddenGlyphAttributes, offset * 3);
589
+ }
590
+ }
591
+
592
+ // For line label layout, we're not using z output and our w input is always 1
593
+ // This custom matrix transformation ignores those components to make projection faster
594
+ function xyTransformMat4(out, a, m) {
595
+ const x = a[0];
596
+ const y = a[1];
597
+ out[0] = m[0] * x + m[4] * y + m[12];
598
+ out[1] = m[1] * x + m[5] * y + m[13];
599
+ out[3] = m[3] * x + m[7] * y + m[15];
600
+ return out;
601
+ }