@deck.gl/extensions 9.0.0-beta.1 → 9.0.0-beta.11

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 (273) hide show
  1. package/dist/brushing/brushing-extension.js +80 -0
  2. package/{typed → dist}/brushing/shader-module.d.ts +1 -1
  3. package/{typed → dist}/brushing/shader-module.d.ts.map +1 -1
  4. package/dist/brushing/shader-module.js +92 -0
  5. package/{typed → dist}/clip/clip-extension.d.ts.map +1 -1
  6. package/dist/clip/clip-extension.js +117 -0
  7. package/{typed → dist}/collision-filter/collision-filter-effect.d.ts +4 -2
  8. package/dist/collision-filter/collision-filter-effect.d.ts.map +1 -0
  9. package/dist/collision-filter/collision-filter-effect.js +194 -0
  10. package/dist/collision-filter/collision-filter-extension.js +49 -0
  11. package/{typed → dist}/collision-filter/collision-filter-pass.d.ts +3 -2
  12. package/dist/collision-filter/collision-filter-pass.d.ts.map +1 -0
  13. package/dist/collision-filter/collision-filter-pass.js +23 -0
  14. package/{typed → dist}/collision-filter/shader-module.d.ts.map +1 -1
  15. package/dist/collision-filter/shader-module.js +87 -0
  16. package/dist/data-filter/aggregator.d.ts.map +1 -0
  17. package/dist/{esm/data-filter → data-filter}/aggregator.js +40 -41
  18. package/{typed → dist}/data-filter/data-filter-extension.d.ts +39 -7
  19. package/dist/data-filter/data-filter-extension.d.ts.map +1 -0
  20. package/dist/data-filter/data-filter-extension.js +256 -0
  21. package/dist/data-filter/shader-module.d.ts +39 -0
  22. package/dist/data-filter/shader-module.d.ts.map +1 -0
  23. package/dist/data-filter/shader-module.js +199 -0
  24. package/dist/dist.dev.js +2667 -11058
  25. package/{typed → dist}/fill-style/fill-style-extension.d.ts +2 -30
  26. package/dist/fill-style/fill-style-extension.d.ts.map +1 -0
  27. package/dist/fill-style/fill-style-extension.js +116 -0
  28. package/{typed/fill-style/shaders.glsl.d.ts → dist/fill-style/shader-module.d.ts} +1 -1
  29. package/dist/fill-style/shader-module.d.ts.map +1 -0
  30. package/dist/fill-style/shader-module.js +96 -0
  31. package/dist/fp64/fp64-extension.js +35 -0
  32. package/dist/fp64/project64.glsl.js +81 -0
  33. package/dist/fp64/project64.js +50 -0
  34. package/dist/index.cjs +2795 -0
  35. package/dist/index.cjs.map +7 -0
  36. package/dist/index.d.ts +19 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +11 -0
  39. package/{typed → dist}/mask/mask-effect.d.ts +6 -5
  40. package/dist/mask/mask-effect.d.ts.map +1 -0
  41. package/dist/mask/mask-effect.js +192 -0
  42. package/dist/mask/mask-extension.js +57 -0
  43. package/dist/mask/mask-pass.d.ts +61 -0
  44. package/dist/mask/mask-pass.d.ts.map +1 -0
  45. package/dist/mask/mask-pass.js +52 -0
  46. package/{typed → dist}/mask/shader-module.d.ts.map +1 -1
  47. package/dist/mask/shader-module.js +77 -0
  48. package/{typed → dist}/path-style/path-style-extension.d.ts.map +1 -1
  49. package/dist/path-style/path-style-extension.js +112 -0
  50. package/dist/path-style/shaders.glsl.js +86 -0
  51. package/{typed → dist}/terrain/height-map-builder.d.ts +1 -1
  52. package/dist/terrain/height-map-builder.d.ts.map +1 -0
  53. package/dist/terrain/height-map-builder.js +104 -0
  54. package/{typed → dist}/terrain/shader-module.d.ts +2 -2
  55. package/dist/terrain/shader-module.d.ts.map +1 -0
  56. package/dist/terrain/shader-module.js +137 -0
  57. package/{typed → dist}/terrain/terrain-cover.d.ts +1 -1
  58. package/dist/terrain/terrain-cover.d.ts.map +1 -0
  59. package/dist/terrain/terrain-cover.js +188 -0
  60. package/{typed → dist}/terrain/terrain-effect.d.ts +6 -7
  61. package/dist/terrain/terrain-effect.d.ts.map +1 -0
  62. package/dist/terrain/terrain-effect.js +174 -0
  63. package/dist/terrain/terrain-extension.js +44 -0
  64. package/dist/terrain/terrain-pass.d.ts +53 -0
  65. package/dist/terrain/terrain-pass.d.ts.map +1 -0
  66. package/dist/terrain/terrain-pass.js +69 -0
  67. package/{typed → dist}/terrain/terrain-picking-pass.d.ts +1 -1
  68. package/dist/terrain/terrain-picking-pass.d.ts.map +1 -0
  69. package/dist/terrain/terrain-picking-pass.js +67 -0
  70. package/{typed → dist}/terrain/utils.d.ts +1 -0
  71. package/{typed → dist}/terrain/utils.d.ts.map +1 -1
  72. package/dist/terrain/utils.js +25 -0
  73. package/{typed → dist}/utils/debug.d.ts.map +1 -1
  74. package/dist/utils/debug.js +50 -0
  75. package/dist/utils/projection-utils.js +153 -0
  76. package/dist/utils/syntax-tags.d.ts +6 -0
  77. package/dist/utils/syntax-tags.d.ts.map +1 -0
  78. package/dist/utils/syntax-tags.js +5 -0
  79. package/dist.min.js +918 -1254
  80. package/package.json +19 -16
  81. package/src/brushing/shader-module.ts +4 -3
  82. package/src/clip/clip-extension.ts +10 -9
  83. package/src/collision-filter/collision-filter-effect.ts +35 -31
  84. package/src/collision-filter/collision-filter-pass.ts +7 -13
  85. package/src/collision-filter/shader-module.ts +6 -4
  86. package/src/data-filter/aggregator.ts +8 -13
  87. package/src/data-filter/data-filter-extension.ts +181 -56
  88. package/src/data-filter/shader-module.ts +132 -37
  89. package/src/fill-style/fill-style-extension.ts +4 -5
  90. package/src/fill-style/{shaders.glsl.ts → shader-module.ts} +6 -5
  91. package/src/mask/mask-effect.ts +30 -20
  92. package/src/mask/mask-pass.ts +22 -18
  93. package/src/mask/shader-module.ts +7 -6
  94. package/src/path-style/path-style-extension.ts +1 -0
  95. package/src/terrain/shader-module.ts +14 -13
  96. package/src/terrain/terrain-cover.ts +2 -1
  97. package/src/terrain/terrain-effect.ts +19 -23
  98. package/src/terrain/terrain-pass.ts +37 -37
  99. package/src/terrain/terrain-picking-pass.ts +19 -25
  100. package/src/terrain/utils.ts +13 -7
  101. package/src/utils/debug.ts +1 -2
  102. package/src/utils/syntax-tags.ts +5 -0
  103. package/dist/es5/brushing/brushing-extension.js +0 -108
  104. package/dist/es5/brushing/brushing-extension.js.map +0 -1
  105. package/dist/es5/brushing/shader-module.js +0 -50
  106. package/dist/es5/brushing/shader-module.js.map +0 -1
  107. package/dist/es5/clip/clip-extension.js +0 -98
  108. package/dist/es5/clip/clip-extension.js.map +0 -1
  109. package/dist/es5/collision-filter/collision-filter-effect.js +0 -294
  110. package/dist/es5/collision-filter/collision-filter-effect.js.map +0 -1
  111. package/dist/es5/collision-filter/collision-filter-extension.js +0 -109
  112. package/dist/es5/collision-filter/collision-filter-extension.js.map +0 -1
  113. package/dist/es5/collision-filter/collision-filter-pass.js +0 -79
  114. package/dist/es5/collision-filter/collision-filter-pass.js.map +0 -1
  115. package/dist/es5/collision-filter/shader-module.js +0 -39
  116. package/dist/es5/collision-filter/shader-module.js.map +0 -1
  117. package/dist/es5/data-filter/aggregator.js +0 -79
  118. package/dist/es5/data-filter/aggregator.js.map +0 -1
  119. package/dist/es5/data-filter/data-filter-extension.js +0 -236
  120. package/dist/es5/data-filter/data-filter-extension.js.map +0 -1
  121. package/dist/es5/data-filter/shader-module.js +0 -122
  122. package/dist/es5/data-filter/shader-module.js.map +0 -1
  123. package/dist/es5/fill-style/fill-style-extension.js +0 -190
  124. package/dist/es5/fill-style/fill-style-extension.js.map +0 -1
  125. package/dist/es5/fill-style/shaders.glsl.js +0 -59
  126. package/dist/es5/fill-style/shaders.glsl.js.map +0 -1
  127. package/dist/es5/fp64/fp64-extension.js +0 -55
  128. package/dist/es5/fp64/fp64-extension.js.map +0 -1
  129. package/dist/es5/fp64/project64.glsl.js +0 -9
  130. package/dist/es5/fp64/project64.glsl.js.map +0 -1
  131. package/dist/es5/fp64/project64.js +0 -52
  132. package/dist/es5/fp64/project64.js.map +0 -1
  133. package/dist/es5/index.js +0 -88
  134. package/dist/es5/index.js.map +0 -1
  135. package/dist/es5/mask/mask-effect.js +0 -279
  136. package/dist/es5/mask/mask-effect.js.map +0 -1
  137. package/dist/es5/mask/mask-extension.js +0 -113
  138. package/dist/es5/mask/mask-extension.js.map +0 -1
  139. package/dist/es5/mask/mask-pass.js +0 -106
  140. package/dist/es5/mask/mask-pass.js.map +0 -1
  141. package/dist/es5/mask/shader-module.js +0 -38
  142. package/dist/es5/mask/shader-module.js.map +0 -1
  143. package/dist/es5/path-style/path-style-extension.js +0 -169
  144. package/dist/es5/path-style/path-style-extension.js.map +0 -1
  145. package/dist/es5/path-style/shaders.glsl.js +0 -25
  146. package/dist/es5/path-style/shaders.glsl.js.map +0 -1
  147. package/dist/es5/terrain/height-map-builder.js +0 -111
  148. package/dist/es5/terrain/height-map-builder.js.map +0 -1
  149. package/dist/es5/terrain/shader-module.js +0 -86
  150. package/dist/es5/terrain/shader-module.js.map +0 -1
  151. package/dist/es5/terrain/terrain-cover.js +0 -256
  152. package/dist/es5/terrain/terrain-cover.js.map +0 -1
  153. package/dist/es5/terrain/terrain-effect.js +0 -326
  154. package/dist/es5/terrain/terrain-effect.js.map +0 -1
  155. package/dist/es5/terrain/terrain-extension.js +0 -94
  156. package/dist/es5/terrain/terrain-extension.js.map +0 -1
  157. package/dist/es5/terrain/terrain-pass.js +0 -121
  158. package/dist/es5/terrain/terrain-pass.js.map +0 -1
  159. package/dist/es5/terrain/terrain-picking-pass.js +0 -124
  160. package/dist/es5/terrain/terrain-picking-pass.js.map +0 -1
  161. package/dist/es5/terrain/utils.js +0 -35
  162. package/dist/es5/terrain/utils.js.map +0 -1
  163. package/dist/es5/utils/debug.js +0 -71
  164. package/dist/es5/utils/debug.js.map +0 -1
  165. package/dist/es5/utils/projection-utils.js +0 -168
  166. package/dist/es5/utils/projection-utils.js.map +0 -1
  167. package/dist/esm/brushing/brushing-extension.js +0 -68
  168. package/dist/esm/brushing/brushing-extension.js.map +0 -1
  169. package/dist/esm/brushing/shader-module.js +0 -103
  170. package/dist/esm/brushing/shader-module.js.map +0 -1
  171. package/dist/esm/clip/clip-extension.js +0 -86
  172. package/dist/esm/clip/clip-extension.js.map +0 -1
  173. package/dist/esm/collision-filter/collision-filter-effect.js +0 -246
  174. package/dist/esm/collision-filter/collision-filter-effect.js.map +0 -1
  175. package/dist/esm/collision-filter/collision-filter-extension.js +0 -75
  176. package/dist/esm/collision-filter/collision-filter-extension.js.map +0 -1
  177. package/dist/esm/collision-filter/collision-filter-pass.js +0 -32
  178. package/dist/esm/collision-filter/collision-filter-pass.js.map +0 -1
  179. package/dist/esm/collision-filter/shader-module.js +0 -104
  180. package/dist/esm/collision-filter/shader-module.js.map +0 -1
  181. package/dist/esm/data-filter/aggregator.js.map +0 -1
  182. package/dist/esm/data-filter/data-filter-extension.js +0 -189
  183. package/dist/esm/data-filter/data-filter-extension.js.map +0 -1
  184. package/dist/esm/data-filter/shader-module.js +0 -164
  185. package/dist/esm/data-filter/shader-module.js.map +0 -1
  186. package/dist/esm/fill-style/fill-style-extension.js +0 -156
  187. package/dist/esm/fill-style/fill-style-extension.js.map +0 -1
  188. package/dist/esm/fill-style/shaders.glsl.js +0 -108
  189. package/dist/esm/fill-style/shaders.glsl.js.map +0 -1
  190. package/dist/esm/fp64/fp64-extension.js +0 -20
  191. package/dist/esm/fp64/fp64-extension.js.map +0 -1
  192. package/dist/esm/fp64/project64.glsl.js +0 -82
  193. package/dist/esm/fp64/project64.glsl.js.map +0 -1
  194. package/dist/esm/fp64/project64.js +0 -43
  195. package/dist/esm/fp64/project64.js.map +0 -1
  196. package/dist/esm/index.js +0 -11
  197. package/dist/esm/index.js.map +0 -1
  198. package/dist/esm/mask/mask-effect.js +0 -228
  199. package/dist/esm/mask/mask-effect.js.map +0 -1
  200. package/dist/esm/mask/mask-extension.js +0 -83
  201. package/dist/esm/mask/mask-extension.js.map +0 -1
  202. package/dist/esm/mask/mask-pass.js +0 -58
  203. package/dist/esm/mask/mask-pass.js.map +0 -1
  204. package/dist/esm/mask/shader-module.js +0 -84
  205. package/dist/esm/mask/shader-module.js.map +0 -1
  206. package/dist/esm/path-style/path-style-extension.js +0 -130
  207. package/dist/esm/path-style/path-style-extension.js.map +0 -1
  208. package/dist/esm/path-style/shaders.glsl.js +0 -84
  209. package/dist/esm/path-style/shaders.glsl.js.map +0 -1
  210. package/dist/esm/terrain/height-map-builder.js +0 -86
  211. package/dist/esm/terrain/height-map-builder.js.map +0 -1
  212. package/dist/esm/terrain/shader-module.js +0 -127
  213. package/dist/esm/terrain/shader-module.js.map +0 -1
  214. package/dist/esm/terrain/terrain-cover.js +0 -212
  215. package/dist/esm/terrain/terrain-cover.js.map +0 -1
  216. package/dist/esm/terrain/terrain-effect.js +0 -219
  217. package/dist/esm/terrain/terrain-effect.js.map +0 -1
  218. package/dist/esm/terrain/terrain-extension.js +0 -59
  219. package/dist/esm/terrain/terrain-extension.js.map +0 -1
  220. package/dist/esm/terrain/terrain-pass.js +0 -71
  221. package/dist/esm/terrain/terrain-pass.js.map +0 -1
  222. package/dist/esm/terrain/terrain-picking-pass.js +0 -73
  223. package/dist/esm/terrain/terrain-picking-pass.js.map +0 -1
  224. package/dist/esm/terrain/utils.js +0 -19
  225. package/dist/esm/terrain/utils.js.map +0 -1
  226. package/dist/esm/utils/debug.js +0 -61
  227. package/dist/esm/utils/debug.js.map +0 -1
  228. package/dist/esm/utils/projection-utils.js +0 -134
  229. package/dist/esm/utils/projection-utils.js.map +0 -1
  230. package/typed/collision-filter/collision-filter-effect.d.ts.map +0 -1
  231. package/typed/collision-filter/collision-filter-pass.d.ts.map +0 -1
  232. package/typed/data-filter/aggregator.d.ts.map +0 -1
  233. package/typed/data-filter/data-filter-extension.d.ts.map +0 -1
  234. package/typed/data-filter/shader-module.d.ts +0 -9
  235. package/typed/data-filter/shader-module.d.ts.map +0 -1
  236. package/typed/fill-style/fill-style-extension.d.ts.map +0 -1
  237. package/typed/fill-style/shaders.glsl.d.ts.map +0 -1
  238. package/typed/index.d.ts +0 -19
  239. package/typed/index.d.ts.map +0 -1
  240. package/typed/mask/mask-effect.d.ts.map +0 -1
  241. package/typed/mask/mask-pass.d.ts +0 -19
  242. package/typed/mask/mask-pass.d.ts.map +0 -1
  243. package/typed/terrain/height-map-builder.d.ts.map +0 -1
  244. package/typed/terrain/shader-module.d.ts.map +0 -1
  245. package/typed/terrain/terrain-cover.d.ts.map +0 -1
  246. package/typed/terrain/terrain-effect.d.ts.map +0 -1
  247. package/typed/terrain/terrain-pass.d.ts +0 -11
  248. package/typed/terrain/terrain-pass.d.ts.map +0 -1
  249. package/typed/terrain/terrain-picking-pass.d.ts.map +0 -1
  250. /package/{typed → dist}/brushing/brushing-extension.d.ts +0 -0
  251. /package/{typed → dist}/brushing/brushing-extension.d.ts.map +0 -0
  252. /package/{typed → dist}/clip/clip-extension.d.ts +0 -0
  253. /package/{typed → dist}/collision-filter/collision-filter-extension.d.ts +0 -0
  254. /package/{typed → dist}/collision-filter/collision-filter-extension.d.ts.map +0 -0
  255. /package/{typed → dist}/collision-filter/shader-module.d.ts +0 -0
  256. /package/{typed → dist}/data-filter/aggregator.d.ts +0 -0
  257. /package/{typed → dist}/fp64/fp64-extension.d.ts +0 -0
  258. /package/{typed → dist}/fp64/fp64-extension.d.ts.map +0 -0
  259. /package/{typed → dist}/fp64/project64.d.ts +0 -0
  260. /package/{typed → dist}/fp64/project64.d.ts.map +0 -0
  261. /package/{typed → dist}/fp64/project64.glsl.d.ts +0 -0
  262. /package/{typed → dist}/fp64/project64.glsl.d.ts.map +0 -0
  263. /package/{typed → dist}/mask/mask-extension.d.ts +0 -0
  264. /package/{typed → dist}/mask/mask-extension.d.ts.map +0 -0
  265. /package/{typed → dist}/mask/shader-module.d.ts +0 -0
  266. /package/{typed → dist}/path-style/path-style-extension.d.ts +0 -0
  267. /package/{typed → dist}/path-style/shaders.glsl.d.ts +0 -0
  268. /package/{typed → dist}/path-style/shaders.glsl.d.ts.map +0 -0
  269. /package/{typed → dist}/terrain/terrain-extension.d.ts +0 -0
  270. /package/{typed → dist}/terrain/terrain-extension.d.ts.map +0 -0
  271. /package/{typed → dist}/utils/debug.d.ts +0 -0
  272. /package/{typed → dist}/utils/projection-utils.d.ts +0 -0
  273. /package/{typed → dist}/utils/projection-utils.d.ts.map +0 -0
@@ -18,32 +18,39 @@
18
18
  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  // THE SOFTWARE.
20
20
 
21
- import {readPixelsToArray, clear, withGLParameters} from '@luma.gl/webgl';
22
- import {GL} from '@luma.gl/constants';
23
21
  import type {Framebuffer} from '@luma.gl/core';
24
22
  import type {Model} from '@luma.gl/engine';
25
23
  import type {Layer, LayerContext, Accessor, UpdateParameters} from '@deck.gl/core';
26
- import {LayerExtension} from '@deck.gl/core';
27
- import {shaderModule, shaderModule64} from './shader-module';
24
+ import {_deepEqual as deepEqual, LayerExtension, log} from '@deck.gl/core';
25
+ import {Defines, shaderModule, shaderModule64} from './shader-module';
28
26
  import * as aggregator from './aggregator';
29
27
 
30
28
  const defaultProps = {
31
29
  getFilterValue: {type: 'accessor', value: 0},
30
+ getFilterCategory: {type: 'accessor', value: 0},
32
31
  onFilteredItemsChange: {type: 'function', value: null, optional: true},
33
32
 
34
33
  filterEnabled: true,
35
34
  filterRange: [-1, 1],
36
35
  filterSoftRange: null,
36
+ filterCategories: [0],
37
37
  filterTransformSize: true,
38
38
  filterTransformColor: true
39
39
  };
40
40
 
41
+ type FilterCategory = number | string;
42
+
41
43
  export type DataFilterExtensionProps<DataT = any> = {
42
44
  /**
43
45
  * Accessor to retrieve the value for each object that it will be filtered by.
44
46
  * Returns either a number (if `filterSize: 1`) or an array of numbers.
45
47
  */
46
48
  getFilterValue?: Accessor<DataT, number | number[]>;
49
+ /**
50
+ * Accessor to retrieve the category (`number | string`) for each object that it will be filtered by.
51
+ * Returns either a single category (if `filterSize: 1`) or an array of categories.
52
+ */
53
+ getFilterCategory?: Accessor<DataT, FilterCategory | FilterCategory[]>;
47
54
  /**
48
55
  * Enable/disable the data filter. If the data filter is disabled, all objects are rendered.
49
56
  * @default true
@@ -71,6 +78,11 @@ export type DataFilterExtensionProps<DataT = any> = {
71
78
  * @default true
72
79
  */
73
80
  filterTransformColor?: boolean;
81
+ /**
82
+ * The categories which define whether an object should be rendered.
83
+ * @default []
84
+ */
85
+ filterCategories: FilterCategory[] | FilterCategory[][];
74
86
  /**
75
87
  * Only called if the `countItems` option is enabled.
76
88
  */
@@ -84,76 +96,110 @@ export type DataFilterExtensionProps<DataT = any> = {
84
96
 
85
97
  type DataFilterExtensionOptions = {
86
98
  /**
87
- * The size of the filter (number of columns to filter by). The data filter can show/hide data based on 1-4 numeric properties of each object.
99
+ * The size of the category filter (number of columns to filter by). The category filter can show/hide data based on 1-4 properties of each object. Set to `0` to disable category filtering.
100
+ * @default 0
101
+ */
102
+ categorySize?: 0 | 1 | 2 | 3 | 4;
103
+ /**
104
+ * The size of the filter (number of columns to filter by). The data filter can show/hide data based on 1-4 numeric properties of each object. Set to `0` to disable numeric filtering.
88
105
  * @default 1
89
106
  */
90
- filterSize: number;
107
+ filterSize?: 0 | 1 | 2 | 3 | 4;
91
108
  /**
92
109
  * Use 64-bit precision instead of 32-bit.
93
110
  * @default false
94
111
  */
95
- fp64: boolean;
112
+ fp64?: boolean;
96
113
  /**
97
114
  * If `true`, reports the number of filtered objects with the `onFilteredItemsChange` callback.
98
115
  * @default `false`.
99
116
  */
100
- countItems: boolean;
117
+ countItems?: boolean;
118
+ };
119
+
120
+ const defaultOptions: Required<DataFilterExtensionOptions> = {
121
+ categorySize: 0,
122
+ filterSize: 1,
123
+ fp64: false,
124
+ countItems: false
101
125
  };
102
126
 
103
127
  const DATA_TYPE_FROM_SIZE = {
104
- 1: 'float',
105
- 2: 'vec2',
106
- 3: 'vec3',
107
- 4: 'vec4'
128
+ 1: 'float' as const,
129
+ 2: 'vec2' as const,
130
+ 3: 'vec3' as const,
131
+ 4: 'vec4' as const
108
132
  };
109
133
 
110
134
  /** Adds GPU-based data filtering functionalities to layers. It allows the layer to show/hide objects based on user-defined properties. */
111
- export default class DataFilterExtension extends LayerExtension<DataFilterExtensionOptions> {
135
+ export default class DataFilterExtension extends LayerExtension<
136
+ Required<DataFilterExtensionOptions>
137
+ > {
112
138
  static defaultProps = defaultProps;
113
139
  static extensionName = 'DataFilterExtension';
114
140
 
115
- constructor({
116
- filterSize = 1,
117
- fp64 = false,
118
- countItems = false
119
- }: Partial<DataFilterExtensionOptions> = {}) {
120
- if (!DATA_TYPE_FROM_SIZE[filterSize]) {
121
- throw new Error('filterSize out of range');
122
- }
123
-
124
- super({filterSize, fp64, countItems});
141
+ constructor(opts: DataFilterExtensionOptions = {}) {
142
+ super({...defaultOptions, ...opts});
125
143
  }
126
144
 
127
145
  getShaders(this: Layer<DataFilterExtensionProps>, extension: this): any {
128
- const {filterSize, fp64} = extension.opts;
146
+ const {categorySize, filterSize, fp64} = extension.opts;
147
+ const defines: Defines = {};
148
+ if (categorySize) {
149
+ defines.DATACATEGORY_TYPE = DATA_TYPE_FROM_SIZE[categorySize];
150
+ defines.DATACATEGORY_CHANNELS = categorySize;
151
+ }
152
+ if (filterSize) {
153
+ defines.DATAFILTER_TYPE = DATA_TYPE_FROM_SIZE[filterSize];
154
+ defines.DATAFILTER_DOUBLE = Boolean(fp64);
155
+ }
129
156
 
130
- return {
131
- modules: [fp64 ? shaderModule64 : shaderModule],
132
- defines: {
133
- DATAFILTER_TYPE: DATA_TYPE_FROM_SIZE[filterSize],
134
- DATAFILTER_DOUBLE: Boolean(fp64)
135
- }
136
- };
157
+ return {modules: [fp64 ? shaderModule64 : shaderModule], defines};
137
158
  }
138
159
 
139
160
  initializeState(this: Layer<DataFilterExtensionProps>, context: LayerContext, extension: this) {
140
161
  const attributeManager = this.getAttributeManager();
162
+ const {categorySize, filterSize, fp64} = extension.opts;
163
+
141
164
  if (attributeManager) {
142
- attributeManager.add({
143
- filterValues: {
144
- size: extension.opts.filterSize,
145
- type: extension.opts.fp64 ? GL.DOUBLE : GL.FLOAT,
146
- accessor: 'getFilterValue',
147
- shaderAttributes: {
148
- filterValues: {
149
- divisor: 0
150
- },
151
- instanceFilterValues: {
152
- divisor: 1
165
+ if (filterSize) {
166
+ attributeManager.add({
167
+ filterValues: {
168
+ size: filterSize,
169
+ type: fp64 ? 'float64' : 'float32',
170
+ accessor: 'getFilterValue',
171
+ shaderAttributes: {
172
+ filterValues: {
173
+ divisor: 0
174
+ },
175
+ instanceFilterValues: {
176
+ divisor: 1
177
+ }
153
178
  }
154
179
  }
155
- }
156
- });
180
+ });
181
+ }
182
+
183
+ if (categorySize) {
184
+ attributeManager.add({
185
+ filterCategoryValues: {
186
+ size: categorySize,
187
+ accessor: 'getFilterCategory',
188
+ transform:
189
+ categorySize === 1
190
+ ? d => extension._getCategoryKey.call(this, d, 0)
191
+ : d => d.map((x, i) => extension._getCategoryKey.call(this, x, i)),
192
+ shaderAttributes: {
193
+ filterCategoryValues: {
194
+ divisor: 0
195
+ },
196
+ instanceFilterCategoryValues: {
197
+ divisor: 1
198
+ }
199
+ }
200
+ }
201
+ });
202
+ }
157
203
  }
158
204
 
159
205
  const {device} = this.context;
@@ -166,8 +212,7 @@ export default class DataFilterExtension extends LayerExtension<DataFilterExtens
166
212
  filterIndices: {
167
213
  size: useFloatTarget ? 1 : 2,
168
214
  vertexOffset: 1,
169
- type: GL.UNSIGNED_BYTE,
170
- normalized: true,
215
+ type: 'unorm8',
171
216
  accessor: (object, {index}) => {
172
217
  const i = object && object.__source ? object.__source.index : index;
173
218
  return useFloatTarget ? (i + 1) % 255 : [(i + 1) % 255, Math.floor(i / 255) % 255];
@@ -195,44 +240,74 @@ export default class DataFilterExtension extends LayerExtension<DataFilterExtens
195
240
 
196
241
  updateState(
197
242
  this: Layer<DataFilterExtensionProps>,
198
- {props, oldProps}: UpdateParameters<Layer<DataFilterExtensionProps>>
243
+ {props, oldProps, changeFlags}: UpdateParameters<Layer<DataFilterExtensionProps>>,
244
+ extension: this
199
245
  ) {
246
+ const attributeManager = this.getAttributeManager();
247
+ const {categorySize} = extension.opts;
200
248
  if (this.state.filterModel) {
201
- const attributeManager = this.getAttributeManager();
202
249
  const filterNeedsUpdate =
203
250
  // attributeManager must be defined for filterModel to be set
204
- attributeManager!.attributes.filterValues.needsUpdate() ||
251
+ attributeManager!.attributes.filterValues?.needsUpdate() ||
252
+ attributeManager!.attributes.filterCategoryValues?.needsUpdate() ||
205
253
  props.filterEnabled !== oldProps.filterEnabled ||
206
254
  props.filterRange !== oldProps.filterRange ||
207
- props.filterSoftRange !== oldProps.filterSoftRange;
255
+ props.filterSoftRange !== oldProps.filterSoftRange ||
256
+ props.filterCategories !== oldProps.filterCategories;
208
257
  if (filterNeedsUpdate) {
209
258
  this.setState({filterNeedsUpdate});
210
259
  }
211
260
  }
261
+ if (attributeManager?.attributes.filterCategoryValues) {
262
+ // Update bitmask if accessor or selected categories has changed
263
+ const categoryBitMaskNeedsUpdate =
264
+ attributeManager.attributes.filterCategoryValues.needsUpdate() ||
265
+ !deepEqual(props.filterCategories, oldProps.filterCategories, 2);
266
+ if (categoryBitMaskNeedsUpdate) {
267
+ this.setState({categoryBitMaskNeedsUpdate});
268
+ }
269
+
270
+ // Need to recreate category map if categorySize has changed
271
+ const resetCategories = changeFlags.dataChanged;
272
+ if (resetCategories) {
273
+ this.setState({
274
+ categoryMap: Array(categorySize)
275
+ .fill(0)
276
+ .map(() => ({}))
277
+ });
278
+ attributeManager.attributes.filterCategoryValues.setNeedsUpdate('categoryMap');
279
+ }
280
+ }
212
281
  }
213
282
 
214
283
  draw(this: Layer<DataFilterExtensionProps>, params: any, extension: this) {
215
284
  const filterFBO = this.state.filterFBO as Framebuffer;
216
285
  const filterModel = this.state.filterModel as Model;
217
286
  const filterNeedsUpdate = this.state.filterNeedsUpdate as boolean;
287
+ const categoryBitMaskNeedsUpdate = this.state.categoryBitMaskNeedsUpdate as boolean;
218
288
 
219
289
  const {onFilteredItemsChange} = this.props;
290
+
291
+ if (categoryBitMaskNeedsUpdate) {
292
+ extension._updateCategoryBitMask.call(this, params, extension);
293
+ }
220
294
  if (filterNeedsUpdate && onFilteredItemsChange && filterModel) {
221
295
  const {
222
- attributes: {filterValues, filterIndices}
296
+ attributes: {filterValues, filterCategoryValues, filterIndices}
223
297
  } = this.getAttributeManager()!;
224
298
  filterModel.setVertexCount(this.getNumInstances());
225
299
 
226
- clear(this.context.device, {framebuffer: filterFBO, color: [0, 0, 0, 0]});
300
+ this.context.device.clearWebGL({framebuffer: filterFBO, color: [0, 0, 0, 0]});
227
301
 
228
302
  filterModel.updateModuleSettings(params.moduleParameters);
229
303
  // @ts-expect-error filterValue and filterIndices should always have buffer value
230
304
  filterModel.setAttributes({
231
- ...filterValues.getValue(),
305
+ ...filterValues?.getValue(),
306
+ ...filterCategoryValues?.getValue(),
232
307
  ...filterIndices?.getValue()
233
308
  });
234
- withGLParameters(
235
- filterModel.device,
309
+ filterModel.setUniforms(params.uniforms);
310
+ filterModel.device.withParametersWebGL(
236
311
  {
237
312
  framebuffer: filterFBO,
238
313
  // ts-ignore 'readonly' cannot be assigned to the mutable type '[GLBlendEquation, GLBlendEquation]'
@@ -243,7 +318,7 @@ export default class DataFilterExtension extends LayerExtension<DataFilterExtens
243
318
  filterModel.draw(this.context.renderPass);
244
319
  }
245
320
  );
246
- const color = readPixelsToArray(filterFBO);
321
+ const color = filterModel.device.readPixelsToArrayWebGL(filterFBO);
247
322
  let count = 0;
248
323
  for (let i = 0; i < color.length; i++) {
249
324
  count += color[i];
@@ -262,4 +337,54 @@ export default class DataFilterExtension extends LayerExtension<DataFilterExtens
262
337
  filterFBO?.destroy();
263
338
  filterModel?.destroy();
264
339
  }
340
+
341
+ /**
342
+ * Updates the bitmask used on the GPU to perform the filter based on the
343
+ * `filterCategories` prop. The mapping between categories and bit in the bitmask
344
+ * is performed by `_getCategoryKey()`
345
+ */
346
+ _updateCategoryBitMask(
347
+ this: Layer<DataFilterExtensionProps>,
348
+ params: any,
349
+ extension: this
350
+ ): void {
351
+ const {categorySize} = extension.opts;
352
+ const {filterCategories} = this.props;
353
+ const categoryBitMask = new Uint32Array([0, 0, 0, 0]);
354
+ const categoryFilters = (
355
+ categorySize === 1 ? [filterCategories] : filterCategories
356
+ ) as FilterCategory[][];
357
+ const maxCategories = categorySize === 1 ? 128 : categorySize === 2 ? 64 : 32;
358
+ for (let c = 0; c < categoryFilters.length; c++) {
359
+ const categoryFilter = categoryFilters[c];
360
+ for (const category of categoryFilter) {
361
+ const key = extension._getCategoryKey.call(this, category, c);
362
+ if (key < maxCategories) {
363
+ const channel = c * (maxCategories / 32) + Math.floor(key / 32);
364
+ categoryBitMask[channel] += Math.pow(2, key % 32); // 1 << key fails for key > 30
365
+ } else {
366
+ log.warn(`Exceeded maximum number of categories (${maxCategories})`)();
367
+ }
368
+ }
369
+ }
370
+ /* eslint-disable-next-line camelcase */
371
+ params.uniforms.filter_categoryBitMask = categoryBitMask;
372
+ this.state.categoryBitMaskNeedsUpdate = false;
373
+ }
374
+
375
+ /**
376
+ * Returns an index of bit in the bitmask for a given category. If the category has
377
+ * not yet been assigned a bit, a new one is assigned.
378
+ */
379
+ _getCategoryKey(
380
+ this: Layer<DataFilterExtensionProps>,
381
+ category: FilterCategory,
382
+ channel: number
383
+ ) {
384
+ const categoryMap = (this.state.categoryMap as Record<FilterCategory, number>[])[channel];
385
+ if (!(category in categoryMap)) {
386
+ categoryMap[category] = Object.keys(categoryMap).length;
387
+ }
388
+ return categoryMap[category];
389
+ }
265
390
  }
@@ -1,32 +1,83 @@
1
1
  import type {ShaderModule} from '@luma.gl/shadertools';
2
2
  import type {DataFilterExtensionProps} from './data-filter-extension';
3
+ import {glsl} from '../utils/syntax-tags';
3
4
 
4
5
  /*
5
6
  * data filter shader module
6
7
  */
7
- const vs = `
8
- uniform DATAFILTER_TYPE filter_min;
9
- uniform DATAFILTER_TYPE filter_softMin;
10
- uniform DATAFILTER_TYPE filter_softMax;
11
- uniform DATAFILTER_TYPE filter_max;
8
+ export type Defines = {
9
+ // Defines passed externally
10
+ /**
11
+ * Primitive type of parameter used for category filtering. If undefined, category filtering disabled.
12
+ */
13
+ DATACATEGORY_TYPE?: 'float' | 'vec2' | 'vec3' | 'vec4';
14
+ /**
15
+ * Number of category filtering channels. Must match dimension of `DATACATEGORY_TYPE`
16
+ */
17
+ DATACATEGORY_CHANNELS?: 1 | 2 | 3 | 4;
18
+
19
+ /**
20
+ * Primitive type of parameter used for numeric filtering. If undefined, numeric filtering disabled.
21
+ */
22
+ DATAFILTER_TYPE?: 'float' | 'vec2' | 'vec3' | 'vec4';
23
+
24
+ /**
25
+ * Enable 64-bit precision in numeric filter.
26
+ */
27
+ DATAFILTER_DOUBLE?: boolean;
28
+
29
+ // Defines derived in shader
30
+ /**
31
+ * Numeric filter attribute
32
+ */
33
+ DATAFILTER_ATTRIB?: 'filterValues' | 'instanceFilterValues';
34
+ /**
35
+ * Numeric filter attribute (low bits). Only used when `DATAFILTER_DOUBLE = true`
36
+ */
37
+ DATAFILTER_ATTRIB_64LOW?: 'filterValues64Low' | 'instanceFilterValues64Low';
38
+ /**
39
+ * Category filter attribute
40
+ */
41
+ DATACATEGORY_ATTRIB?: 'filterCategoryValues' | 'instanceFilterCategoryValues';
42
+ };
43
+
44
+ const vs = glsl`
12
45
  uniform bool filter_useSoftMargin;
13
46
  uniform bool filter_enabled;
14
47
  uniform bool filter_transformSize;
48
+ uniform ivec4 filter_categoryBitMask;
49
+
50
+ #ifdef DATAFILTER_TYPE
51
+ uniform DATAFILTER_TYPE filter_min;
52
+ uniform DATAFILTER_TYPE filter_softMin;
53
+ uniform DATAFILTER_TYPE filter_softMax;
54
+ uniform DATAFILTER_TYPE filter_max;
55
+
56
+ #ifdef NON_INSTANCED_MODEL
57
+ #define DATAFILTER_ATTRIB filterValues
58
+ #define DATAFILTER_ATTRIB_64LOW filterValues64Low
59
+ #else
60
+ #define DATAFILTER_ATTRIB instanceFilterValues
61
+ #define DATAFILTER_ATTRIB_64LOW instanceFilterValues64Low
62
+ #endif
63
+
64
+ in DATAFILTER_TYPE DATAFILTER_ATTRIB;
65
+ #ifdef DATAFILTER_DOUBLE
66
+ in DATAFILTER_TYPE DATAFILTER_ATTRIB_64LOW;
15
67
 
16
- #ifdef NON_INSTANCED_MODEL
17
- #define DATAFILTER_ATTRIB filterValues
18
- #define DATAFILTER_ATTRIB_64LOW filterValues64Low
19
- #else
20
- #define DATAFILTER_ATTRIB instanceFilterValues
21
- #define DATAFILTER_ATTRIB_64LOW instanceFilterValues64Low
68
+ uniform DATAFILTER_TYPE filter_min64High;
69
+ uniform DATAFILTER_TYPE filter_max64High;
70
+ #endif
22
71
  #endif
23
72
 
24
- in DATAFILTER_TYPE DATAFILTER_ATTRIB;
25
- #ifdef DATAFILTER_DOUBLE
26
- in DATAFILTER_TYPE DATAFILTER_ATTRIB_64LOW;
27
73
 
28
- uniform DATAFILTER_TYPE filter_min64High;
29
- uniform DATAFILTER_TYPE filter_max64High;
74
+ #ifdef DATACATEGORY_TYPE
75
+ #ifdef NON_INSTANCED_MODEL
76
+ #define DATACATEGORY_ATTRIB filterCategoryValues
77
+ #else
78
+ #define DATACATEGORY_ATTRIB instanceFilterCategoryValues
79
+ #endif
80
+ in DATACATEGORY_TYPE DATACATEGORY_ATTRIB;
30
81
  #endif
31
82
 
32
83
  out float dataFilter_value;
@@ -43,25 +94,60 @@ float dataFilter_reduceValue(vec3 value) {
43
94
  float dataFilter_reduceValue(vec4 value) {
44
95
  return min(min(value.x, value.y), min(value.z, value.w));
45
96
  }
46
- void dataFilter_setValue(DATAFILTER_TYPE valueFromMin, DATAFILTER_TYPE valueFromMax) {
47
- if (filter_enabled) {
97
+
98
+ #ifdef DATAFILTER_TYPE
99
+ void dataFilter_setValue(DATAFILTER_TYPE valueFromMin, DATAFILTER_TYPE valueFromMax) {
48
100
  if (filter_useSoftMargin) {
49
- dataFilter_value = dataFilter_reduceValue(
50
- smoothstep(filter_min, filter_softMin, valueFromMin) *
51
- (1.0 - smoothstep(filter_softMax, filter_max, valueFromMax))
101
+ // smoothstep results are undefined if edge0 ≥ edge1
102
+ // Fallback to ignore filterSoftRange if it is truncated by filterRange
103
+ DATAFILTER_TYPE leftInRange = mix(
104
+ smoothstep(filter_min, filter_softMin, valueFromMin),
105
+ step(filter_min, valueFromMin),
106
+ step(filter_softMin, filter_min)
52
107
  );
108
+ DATAFILTER_TYPE rightInRange = mix(
109
+ 1.0 - smoothstep(filter_softMax, filter_max, valueFromMax),
110
+ step(valueFromMax, filter_max),
111
+ step(filter_max, filter_softMax)
112
+ );
113
+ dataFilter_value = dataFilter_reduceValue(leftInRange * rightInRange);
53
114
  } else {
54
115
  dataFilter_value = dataFilter_reduceValue(
55
116
  step(filter_min, valueFromMin) * step(valueFromMax, filter_max)
56
117
  );
57
118
  }
58
- } else {
59
- dataFilter_value = 1.0;
60
119
  }
61
- }
120
+ #endif
121
+
122
+ #ifdef DATACATEGORY_ATTRIB
123
+ void dataFilter_setCategoryValue(DATACATEGORY_TYPE category) {
124
+ #if DATACATEGORY_CHANNELS == 1 // One 128-bit mask
125
+ int dataFilter_masks = filter_categoryBitMask[int(category / 32.0)];
126
+ #elif DATACATEGORY_CHANNELS == 2 // Two 64-bit masks
127
+ ivec2 dataFilter_masks = ivec2(
128
+ filter_categoryBitMask[int(category.x / 32.0)],
129
+ filter_categoryBitMask[int(category.y / 32.0) + 2]
130
+ );
131
+ #elif DATACATEGORY_CHANNELS == 3 // Three 32-bit masks
132
+ ivec3 dataFilter_masks = filter_categoryBitMask.xyz;
133
+ #else // Four 32-bit masks
134
+ ivec4 dataFilter_masks = filter_categoryBitMask;
135
+ #endif
136
+
137
+ // Shift mask and extract relevant bits
138
+ DATACATEGORY_TYPE dataFilter_bits = DATACATEGORY_TYPE(dataFilter_masks) / pow(DATACATEGORY_TYPE(2.0), mod(category, 32.0));
139
+ dataFilter_bits = mod(floor(dataFilter_bits), 2.0);
140
+
141
+ #if DATACATEGORY_CHANNELS == 1
142
+ if(dataFilter_bits == 0.0) dataFilter_value = 0.0;
143
+ #else
144
+ if(any(equal(dataFilter_bits, DATACATEGORY_TYPE(0.0)))) dataFilter_value = 0.0;
145
+ #endif
146
+ }
147
+ #endif
62
148
  `;
63
149
 
64
- const fs = `
150
+ const fs = glsl`
65
151
  uniform bool filter_transformColor;
66
152
  in float dataFilter_value;
67
153
  `;
@@ -134,30 +220,39 @@ function getUniforms64(opts?: DataFilterModuleSettings | {}): Record<string, any
134
220
  }
135
221
 
136
222
  const inject = {
137
- 'vs:#main-start': `
138
- #ifdef DATAFILTER_DOUBLE
139
- dataFilter_setValue(
140
- DATAFILTER_ATTRIB - filter_min64High + DATAFILTER_ATTRIB_64LOW,
141
- DATAFILTER_ATTRIB - filter_max64High + DATAFILTER_ATTRIB_64LOW
142
- );
143
- #else
144
- dataFilter_setValue(DATAFILTER_ATTRIB, DATAFILTER_ATTRIB);
145
- #endif
223
+ 'vs:#main-start': glsl`
224
+ dataFilter_value = 1.0;
225
+ if (filter_enabled) {
226
+ #ifdef DATAFILTER_ATTRIB
227
+ #ifdef DATAFILTER_DOUBLE
228
+ dataFilter_setValue(
229
+ DATAFILTER_ATTRIB - filter_min64High + DATAFILTER_ATTRIB_64LOW,
230
+ DATAFILTER_ATTRIB - filter_max64High + DATAFILTER_ATTRIB_64LOW
231
+ );
232
+ #else
233
+ dataFilter_setValue(DATAFILTER_ATTRIB, DATAFILTER_ATTRIB);
234
+ #endif
235
+ #endif
236
+
237
+ #ifdef DATACATEGORY_ATTRIB
238
+ dataFilter_setCategoryValue(DATACATEGORY_ATTRIB);
239
+ #endif
240
+ }
146
241
  `,
147
242
 
148
- 'vs:#main-end': `
243
+ 'vs:#main-end': glsl`
149
244
  if (dataFilter_value == 0.0) {
150
245
  gl_Position = vec4(0.);
151
246
  }
152
247
  `,
153
248
 
154
- 'vs:DECKGL_FILTER_SIZE': `
249
+ 'vs:DECKGL_FILTER_SIZE': glsl`
155
250
  if (filter_transformSize) {
156
251
  size = size * dataFilter_value;
157
252
  }
158
253
  `,
159
254
 
160
- 'fs:DECKGL_FILTER_COLOR': `
255
+ 'fs:DECKGL_FILTER_COLOR': glsl`
161
256
  if (dataFilter_value == 0.0) discard;
162
257
  if (filter_transformColor) {
163
258
  color.a *= dataFilter_value;
@@ -1,10 +1,11 @@
1
1
  import {LayerExtension} from '@deck.gl/core';
2
2
 
3
- import {patternShaders} from './shaders.glsl';
3
+ import {patternShaders} from './shader-module';
4
4
 
5
5
  import type {
6
6
  Layer,
7
7
  LayerContext,
8
+ DefaultProps,
8
9
  Accessor,
9
10
  AccessorFunction,
10
11
  TextureSource,
@@ -12,15 +13,13 @@ import type {
12
13
  } from '@deck.gl/core';
13
14
  import type {Texture} from '@luma.gl/core';
14
15
 
15
- const defaultProps = {
16
+ const defaultProps: DefaultProps<FillStyleExtensionProps> = {
16
17
  fillPatternEnabled: true,
17
18
  fillPatternAtlas: {
18
19
  type: 'image',
19
20
  value: null,
20
21
  async: true,
21
- parameters: {
22
- minFilter: 'linear'
23
- }
22
+ parameters: {lodMaxClamp: 0}
24
23
  },
25
24
  fillPatternMapping: {type: 'object', value: {}, async: true},
26
25
  fillPatternMask: true,
@@ -3,11 +3,12 @@ import {project, fp64LowPart} from '@deck.gl/core';
3
3
  import type {Viewport, ProjectUniforms} from '@deck.gl/core';
4
4
 
5
5
  import type {Texture} from '@luma.gl/core';
6
+ import {glsl} from '../utils/syntax-tags';
6
7
 
7
8
  /*
8
9
  * fill pattern shader module
9
10
  */
10
- const patternVs = `
11
+ const patternVs = glsl`
11
12
  #ifdef NON_INSTANCED_MODEL
12
13
  #define FILL_PATTERN_FRAME_ATTRIB fillPatternFrames
13
14
  #define FILL_PATTERN_SCALE_ATTRIB fillPatternScales
@@ -30,7 +31,7 @@ out vec4 fill_patternBounds;
30
31
  out vec4 fill_patternPlacement;
31
32
  `;
32
33
 
33
- const patternFs = `
34
+ const patternFs = glsl`
34
35
  uniform bool fill_patternEnabled;
35
36
  uniform bool fill_patternMask;
36
37
  uniform sampler2D fill_patternTexture;
@@ -45,11 +46,11 @@ const float FILL_UV_SCALE = 512.0 / 40000000.0;
45
46
  `;
46
47
 
47
48
  const inject = {
48
- 'vs:DECKGL_FILTER_GL_POSITION': `
49
+ 'vs:DECKGL_FILTER_GL_POSITION': glsl`
49
50
  fill_uv = geometry.position.xy;
50
51
  `,
51
52
 
52
- 'vs:DECKGL_FILTER_COLOR': `
53
+ 'vs:DECKGL_FILTER_COLOR': glsl`
53
54
  if (fill_patternEnabled) {
54
55
  fill_patternBounds = FILL_PATTERN_FRAME_ATTRIB / vec4(fill_patternTextureSize, fill_patternTextureSize);
55
56
  fill_patternPlacement.xy = FILL_PATTERN_OFFSET_ATTRIB;
@@ -57,7 +58,7 @@ const inject = {
57
58
  }
58
59
  `,
59
60
 
60
- 'fs:DECKGL_FILTER_COLOR': `
61
+ 'fs:DECKGL_FILTER_COLOR': glsl`
61
62
  if (fill_patternEnabled) {
62
63
  vec2 scale = FILL_UV_SCALE * fill_patternPlacement.zw;
63
64
  vec2 patternUV = mod(mod(fill_uvCoordinateOrigin, scale) + fill_uvCoordinateOrigin64Low + fill_uv, scale) / scale;