@deck.gl/extensions 9.0.0-beta.10 → 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.
- package/dist/collision-filter/collision-filter-effect.d.ts +4 -2
- package/dist/collision-filter/collision-filter-effect.d.ts.map +1 -1
- package/dist/collision-filter/collision-filter-effect.js +10 -9
- package/dist/collision-filter/collision-filter-pass.d.ts +3 -2
- package/dist/collision-filter/collision-filter-pass.d.ts.map +1 -1
- package/dist/collision-filter/collision-filter-pass.js +5 -7
- package/dist/data-filter/data-filter-extension.d.ts +5 -5
- package/dist/data-filter/data-filter-extension.d.ts.map +1 -1
- package/dist/data-filter/data-filter-extension.js +45 -38
- package/dist/data-filter/shader-module.d.ts +30 -0
- package/dist/data-filter/shader-module.d.ts.map +1 -1
- package/dist/data-filter/shader-module.js +40 -20
- package/dist/dist.dev.js +571 -535
- package/dist/index.cjs +517 -478
- package/dist/index.cjs.map +4 -4
- package/dist/mask/mask-effect.d.ts +5 -4
- package/dist/mask/mask-effect.d.ts.map +1 -1
- package/dist/mask/mask-effect.js +9 -11
- package/dist/mask/mask-pass.d.ts +45 -3
- package/dist/mask/mask-pass.d.ts.map +1 -1
- package/dist/mask/mask-pass.js +17 -9
- package/dist/path-style/path-style-extension.d.ts.map +1 -1
- package/dist/path-style/path-style-extension.js +1 -0
- package/dist/terrain/terrain-cover.d.ts.map +1 -1
- package/dist/terrain/terrain-cover.js +2 -1
- package/dist/terrain/terrain-effect.d.ts +4 -5
- package/dist/terrain/terrain-effect.d.ts.map +1 -1
- package/dist/terrain/terrain-effect.js +6 -16
- package/dist/terrain/terrain-pass.d.ts +42 -0
- package/dist/terrain/terrain-pass.d.ts.map +1 -1
- package/dist/terrain/terrain-pass.js +24 -16
- package/dist/terrain/terrain-picking-pass.d.ts.map +1 -1
- package/dist/terrain/terrain-picking-pass.js +9 -8
- package/dist/terrain/utils.d.ts +1 -0
- package/dist/terrain/utils.d.ts.map +1 -1
- package/dist/terrain/utils.js +10 -6
- package/dist.min.js +63 -40
- package/package.json +6 -6
- package/src/collision-filter/collision-filter-effect.ts +23 -23
- package/src/collision-filter/collision-filter-pass.ts +7 -11
- package/src/data-filter/data-filter-extension.ts +57 -49
- package/src/data-filter/shader-module.ts +109 -43
- package/src/mask/mask-effect.ts +30 -19
- package/src/mask/mask-pass.ts +22 -16
- package/src/path-style/path-style-extension.ts +1 -0
- package/src/terrain/terrain-cover.ts +2 -1
- package/src/terrain/terrain-effect.ts +8 -19
- package/src/terrain/terrain-pass.ts +37 -34
- package/src/terrain/terrain-picking-pass.ts +19 -23
- package/src/terrain/utils.ts +12 -6
|
@@ -22,7 +22,7 @@ import type {Framebuffer} from '@luma.gl/core';
|
|
|
22
22
|
import type {Model} from '@luma.gl/engine';
|
|
23
23
|
import type {Layer, LayerContext, Accessor, UpdateParameters} from '@deck.gl/core';
|
|
24
24
|
import {_deepEqual as deepEqual, LayerExtension, log} from '@deck.gl/core';
|
|
25
|
-
import {shaderModule, shaderModule64} from './shader-module';
|
|
25
|
+
import {Defines, shaderModule, shaderModule64} from './shader-module';
|
|
26
26
|
import * as aggregator from './aggregator';
|
|
27
27
|
|
|
28
28
|
const defaultProps = {
|
|
@@ -96,15 +96,15 @@ export type DataFilterExtensionProps<DataT = any> = {
|
|
|
96
96
|
|
|
97
97
|
type DataFilterExtensionOptions = {
|
|
98
98
|
/**
|
|
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.
|
|
100
|
-
* @default
|
|
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
101
|
*/
|
|
102
|
-
categorySize?: 1 | 2 | 3 | 4;
|
|
102
|
+
categorySize?: 0 | 1 | 2 | 3 | 4;
|
|
103
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.
|
|
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.
|
|
105
105
|
* @default 1
|
|
106
106
|
*/
|
|
107
|
-
filterSize?: 1 | 2 | 3 | 4;
|
|
107
|
+
filterSize?: 0 | 1 | 2 | 3 | 4;
|
|
108
108
|
/**
|
|
109
109
|
* Use 64-bit precision instead of 32-bit.
|
|
110
110
|
* @default false
|
|
@@ -118,17 +118,17 @@ type DataFilterExtensionOptions = {
|
|
|
118
118
|
};
|
|
119
119
|
|
|
120
120
|
const defaultOptions: Required<DataFilterExtensionOptions> = {
|
|
121
|
-
categorySize:
|
|
121
|
+
categorySize: 0,
|
|
122
122
|
filterSize: 1,
|
|
123
123
|
fp64: false,
|
|
124
124
|
countItems: false
|
|
125
125
|
};
|
|
126
126
|
|
|
127
127
|
const DATA_TYPE_FROM_SIZE = {
|
|
128
|
-
1: 'float',
|
|
129
|
-
2: 'vec2',
|
|
130
|
-
3: 'vec3',
|
|
131
|
-
4: 'vec4'
|
|
128
|
+
1: 'float' as const,
|
|
129
|
+
2: 'vec2' as const,
|
|
130
|
+
3: 'vec3' as const,
|
|
131
|
+
4: 'vec4' as const
|
|
132
132
|
};
|
|
133
133
|
|
|
134
134
|
/** Adds GPU-based data filtering functionalities to layers. It allows the layer to show/hide objects based on user-defined properties. */
|
|
@@ -144,16 +144,17 @@ export default class DataFilterExtension extends LayerExtension<
|
|
|
144
144
|
|
|
145
145
|
getShaders(this: Layer<DataFilterExtensionProps>, extension: this): any {
|
|
146
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
|
+
}
|
|
147
156
|
|
|
148
|
-
return {
|
|
149
|
-
modules: [fp64 ? shaderModule64 : shaderModule],
|
|
150
|
-
defines: {
|
|
151
|
-
DATACATEGORY_TYPE: DATA_TYPE_FROM_SIZE[categorySize],
|
|
152
|
-
DATACATEGORY_CHANNELS: categorySize,
|
|
153
|
-
DATAFILTER_TYPE: DATA_TYPE_FROM_SIZE[filterSize],
|
|
154
|
-
DATAFILTER_DOUBLE: Boolean(fp64)
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
+
return {modules: [fp64 ? shaderModule64 : shaderModule], defines};
|
|
157
158
|
}
|
|
158
159
|
|
|
159
160
|
initializeState(this: Layer<DataFilterExtensionProps>, context: LayerContext, extension: this) {
|
|
@@ -161,37 +162,44 @@ export default class DataFilterExtension extends LayerExtension<
|
|
|
161
162
|
const {categorySize, filterSize, fp64} = extension.opts;
|
|
162
163
|
|
|
163
164
|
if (attributeManager) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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
|
+
}
|
|
175
178
|
}
|
|
176
179
|
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
+
}
|
|
191
199
|
}
|
|
192
200
|
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
195
203
|
}
|
|
196
204
|
|
|
197
205
|
const {device} = this.context;
|
|
@@ -240,7 +248,7 @@ export default class DataFilterExtension extends LayerExtension<
|
|
|
240
248
|
if (this.state.filterModel) {
|
|
241
249
|
const filterNeedsUpdate =
|
|
242
250
|
// attributeManager must be defined for filterModel to be set
|
|
243
|
-
attributeManager!.attributes.filterValues
|
|
251
|
+
attributeManager!.attributes.filterValues?.needsUpdate() ||
|
|
244
252
|
attributeManager!.attributes.filterCategoryValues?.needsUpdate() ||
|
|
245
253
|
props.filterEnabled !== oldProps.filterEnabled ||
|
|
246
254
|
props.filterRange !== oldProps.filterRange ||
|
|
@@ -294,7 +302,7 @@ export default class DataFilterExtension extends LayerExtension<
|
|
|
294
302
|
filterModel.updateModuleSettings(params.moduleParameters);
|
|
295
303
|
// @ts-expect-error filterValue and filterIndices should always have buffer value
|
|
296
304
|
filterModel.setAttributes({
|
|
297
|
-
...filterValues
|
|
305
|
+
...filterValues?.getValue(),
|
|
298
306
|
...filterCategoryValues?.getValue(),
|
|
299
307
|
...filterIndices?.getValue()
|
|
300
308
|
});
|
|
@@ -5,34 +5,80 @@ import {glsl} from '../utils/syntax-tags';
|
|
|
5
5
|
/*
|
|
6
6
|
* data filter shader module
|
|
7
7
|
*/
|
|
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
|
+
|
|
8
44
|
const vs = glsl`
|
|
9
|
-
uniform DATAFILTER_TYPE filter_min;
|
|
10
|
-
uniform DATAFILTER_TYPE filter_softMin;
|
|
11
|
-
uniform DATAFILTER_TYPE filter_softMax;
|
|
12
|
-
uniform DATAFILTER_TYPE filter_max;
|
|
13
45
|
uniform bool filter_useSoftMargin;
|
|
14
46
|
uniform bool filter_enabled;
|
|
15
47
|
uniform bool filter_transformSize;
|
|
16
48
|
uniform ivec4 filter_categoryBitMask;
|
|
17
49
|
|
|
18
|
-
#ifdef
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
#
|
|
25
|
-
|
|
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;
|
|
67
|
+
|
|
68
|
+
uniform DATAFILTER_TYPE filter_min64High;
|
|
69
|
+
uniform DATAFILTER_TYPE filter_max64High;
|
|
70
|
+
#endif
|
|
26
71
|
#endif
|
|
27
72
|
|
|
28
|
-
in DATAFILTER_TYPE DATAFILTER_ATTRIB;
|
|
29
|
-
#ifdef DATAFILTER_DOUBLE
|
|
30
|
-
in DATAFILTER_TYPE DATAFILTER_ATTRIB_64LOW;
|
|
31
73
|
|
|
32
|
-
|
|
33
|
-
|
|
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;
|
|
34
81
|
#endif
|
|
35
|
-
in DATACATEGORY_TYPE DATACATEGORY_ATTRIB;
|
|
36
82
|
|
|
37
83
|
out float dataFilter_value;
|
|
38
84
|
|
|
@@ -48,30 +94,44 @@ float dataFilter_reduceValue(vec3 value) {
|
|
|
48
94
|
float dataFilter_reduceValue(vec4 value) {
|
|
49
95
|
return min(min(value.x, value.y), min(value.z, value.w));
|
|
50
96
|
}
|
|
51
|
-
|
|
52
|
-
|
|
97
|
+
|
|
98
|
+
#ifdef DATAFILTER_TYPE
|
|
99
|
+
void dataFilter_setValue(DATAFILTER_TYPE valueFromMin, DATAFILTER_TYPE valueFromMax) {
|
|
53
100
|
if (filter_useSoftMargin) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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)
|
|
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)
|
|
57
112
|
);
|
|
113
|
+
dataFilter_value = dataFilter_reduceValue(leftInRange * rightInRange);
|
|
58
114
|
} else {
|
|
59
115
|
dataFilter_value = dataFilter_reduceValue(
|
|
60
116
|
step(filter_min, valueFromMin) * step(valueFromMax, filter_max)
|
|
61
117
|
);
|
|
62
118
|
}
|
|
119
|
+
}
|
|
120
|
+
#endif
|
|
63
121
|
|
|
122
|
+
#ifdef DATACATEGORY_ATTRIB
|
|
123
|
+
void dataFilter_setCategoryValue(DATACATEGORY_TYPE category) {
|
|
64
124
|
#if DATACATEGORY_CHANNELS == 1 // One 128-bit mask
|
|
65
|
-
|
|
125
|
+
int dataFilter_masks = filter_categoryBitMask[int(category / 32.0)];
|
|
66
126
|
#elif DATACATEGORY_CHANNELS == 2 // Two 64-bit masks
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
127
|
+
ivec2 dataFilter_masks = ivec2(
|
|
128
|
+
filter_categoryBitMask[int(category.x / 32.0)],
|
|
129
|
+
filter_categoryBitMask[int(category.y / 32.0) + 2]
|
|
130
|
+
);
|
|
71
131
|
#elif DATACATEGORY_CHANNELS == 3 // Three 32-bit masks
|
|
72
|
-
|
|
132
|
+
ivec3 dataFilter_masks = filter_categoryBitMask.xyz;
|
|
73
133
|
#else // Four 32-bit masks
|
|
74
|
-
|
|
134
|
+
ivec4 dataFilter_masks = filter_categoryBitMask;
|
|
75
135
|
#endif
|
|
76
136
|
|
|
77
137
|
// Shift mask and extract relevant bits
|
|
@@ -79,14 +139,12 @@ void dataFilter_setValue(DATAFILTER_TYPE valueFromMin, DATAFILTER_TYPE valueFrom
|
|
|
79
139
|
dataFilter_bits = mod(floor(dataFilter_bits), 2.0);
|
|
80
140
|
|
|
81
141
|
#if DATACATEGORY_CHANNELS == 1
|
|
82
|
-
|
|
142
|
+
if(dataFilter_bits == 0.0) dataFilter_value = 0.0;
|
|
83
143
|
#else
|
|
84
144
|
if(any(equal(dataFilter_bits, DATACATEGORY_TYPE(0.0)))) dataFilter_value = 0.0;
|
|
85
145
|
#endif
|
|
86
|
-
} else {
|
|
87
|
-
dataFilter_value = 1.0;
|
|
88
146
|
}
|
|
89
|
-
|
|
147
|
+
#endif
|
|
90
148
|
`;
|
|
91
149
|
|
|
92
150
|
const fs = glsl`
|
|
@@ -163,15 +221,23 @@ function getUniforms64(opts?: DataFilterModuleSettings | {}): Record<string, any
|
|
|
163
221
|
|
|
164
222
|
const inject = {
|
|
165
223
|
'vs:#main-start': glsl`
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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
|
+
}
|
|
175
241
|
`,
|
|
176
242
|
|
|
177
243
|
'vs:#main-end': glsl`
|
package/src/mask/mask-effect.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
Layer,
|
|
3
|
+
Viewport,
|
|
4
|
+
Effect,
|
|
5
|
+
EffectContext,
|
|
6
|
+
PreRenderOptions,
|
|
7
|
+
CoordinateSystem,
|
|
8
|
+
log
|
|
9
|
+
} from '@deck.gl/core';
|
|
10
|
+
import type {Texture} from '@luma.gl/core';
|
|
3
11
|
import {equals} from '@math.gl/core';
|
|
4
12
|
import MaskPass from './mask-pass';
|
|
5
13
|
import {joinLayerBounds, getRenderBounds, makeViewport, Bounds} from '../utils/projection-utils';
|
|
@@ -7,7 +15,7 @@ import {joinLayerBounds, getRenderBounds, makeViewport, Bounds} from '../utils/p
|
|
|
7
15
|
|
|
8
16
|
type Mask = {
|
|
9
17
|
/** The channel index */
|
|
10
|
-
index:
|
|
18
|
+
index: 0 | 1 | 2 | 3;
|
|
11
19
|
bounds: Bounds;
|
|
12
20
|
coordinateOrigin: [number, number, number];
|
|
13
21
|
coordinateSystem: CoordinateSystem;
|
|
@@ -15,7 +23,7 @@ type Mask = {
|
|
|
15
23
|
|
|
16
24
|
type Channel = {
|
|
17
25
|
id: string;
|
|
18
|
-
index:
|
|
26
|
+
index: 0 | 1 | 2 | 3;
|
|
19
27
|
layers: Layer[];
|
|
20
28
|
bounds: Bounds | null;
|
|
21
29
|
maskBounds: Bounds;
|
|
@@ -42,17 +50,25 @@ export default class MaskEffect implements Effect {
|
|
|
42
50
|
private maskMap?: Texture;
|
|
43
51
|
private lastViewport?: Viewport;
|
|
44
52
|
|
|
45
|
-
|
|
46
|
-
device
|
|
47
|
-
|
|
48
|
-
|
|
53
|
+
setup({device}: EffectContext) {
|
|
54
|
+
this.dummyMaskMap = device.createTexture({
|
|
55
|
+
width: 1,
|
|
56
|
+
height: 1
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
this.maskPass = new MaskPass(device, {id: 'default-mask'});
|
|
60
|
+
this.maskMap = this.maskPass.maskMap;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
preRender({
|
|
64
|
+
layers,
|
|
65
|
+
layerFilter,
|
|
66
|
+
viewports,
|
|
67
|
+
onViewportActive,
|
|
68
|
+
views,
|
|
69
|
+
isPicking
|
|
70
|
+
}: PreRenderOptions): MaskPreRenderStats {
|
|
49
71
|
let didRender = false;
|
|
50
|
-
if (!this.dummyMaskMap) {
|
|
51
|
-
this.dummyMaskMap = device.createTexture({
|
|
52
|
-
width: 1,
|
|
53
|
-
height: 1
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
72
|
|
|
57
73
|
if (isPicking) {
|
|
58
74
|
// Do not update on picking pass
|
|
@@ -67,11 +83,6 @@ export default class MaskEffect implements Effect {
|
|
|
67
83
|
}
|
|
68
84
|
this.masks = {};
|
|
69
85
|
|
|
70
|
-
if (!this.maskPass) {
|
|
71
|
-
this.maskPass = new MaskPass(device, {id: 'default-mask'});
|
|
72
|
-
this.maskMap = this.maskPass.maskMap;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
86
|
// Map layers to channels
|
|
76
87
|
const channelMap = this._sortMaskChannels(maskLayers);
|
|
77
88
|
// TODO - support multiple views
|
package/src/mask/mask-pass.ts
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
import type {Device, Framebuffer, Texture} from '@luma.gl/core';
|
|
2
|
-
import {
|
|
3
|
-
import {_LayersPass as LayersPass, LayersPassRenderOptions} from '@deck.gl/core';
|
|
1
|
+
import type {Device, Framebuffer, RenderPipelineParameters, Texture} from '@luma.gl/core';
|
|
2
|
+
import {Layer, _LayersPass as LayersPass, LayersPassRenderOptions, Viewport} from '@deck.gl/core';
|
|
4
3
|
|
|
5
4
|
type MaskPassRenderOptions = LayersPassRenderOptions & {
|
|
6
5
|
/** The channel to render into, 0:red, 1:green, 2:blue, 3:alpha */
|
|
7
|
-
channel:
|
|
6
|
+
channel: 0 | 1 | 2 | 3;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const MASK_BLENDING: RenderPipelineParameters = {
|
|
10
|
+
blendColorOperation: 'subtract',
|
|
11
|
+
blendColorSrcFactor: 'zero',
|
|
12
|
+
blendColorDstFactor: 'one',
|
|
13
|
+
blendAlphaOperation: 'subtract',
|
|
14
|
+
blendAlphaSrcFactor: 'zero',
|
|
15
|
+
blendAlphaDstFactor: 'one'
|
|
8
16
|
};
|
|
9
17
|
|
|
10
18
|
export default class MaskPass extends LayersPass {
|
|
@@ -37,20 +45,18 @@ export default class MaskPass extends LayersPass {
|
|
|
37
45
|
}
|
|
38
46
|
|
|
39
47
|
render(options: MaskPassRenderOptions) {
|
|
40
|
-
const colorMask =
|
|
41
|
-
colorMask[options.channel] = true;
|
|
48
|
+
const colorMask = 2 ** options.channel;
|
|
42
49
|
const clearColor = [255, 255, 255, 255];
|
|
50
|
+
super.render({...options, clearColor, colorMask, target: this.fbo, pass: 'mask'});
|
|
51
|
+
}
|
|
43
52
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
},
|
|
52
|
-
() => super.render({...options, clearColor, target: this.fbo, pass: 'mask'})
|
|
53
|
-
);
|
|
53
|
+
protected getLayerParameters(layer: Layer<{}>, layerIndex: number, viewport: Viewport) {
|
|
54
|
+
return {
|
|
55
|
+
...layer.props.parameters,
|
|
56
|
+
blend: true,
|
|
57
|
+
depthTest: false,
|
|
58
|
+
...MASK_BLENDING
|
|
59
|
+
};
|
|
54
60
|
}
|
|
55
61
|
|
|
56
62
|
shouldDrawLayer(layer) {
|
|
@@ -174,7 +174,8 @@ export class TerrainCover {
|
|
|
174
174
|
}
|
|
175
175
|
if (!this.pickingFbo) {
|
|
176
176
|
this.pickingFbo = createRenderTarget(this.targetLayer.context.device, {
|
|
177
|
-
id: `${this.id}-picking
|
|
177
|
+
id: `${this.id}-picking`,
|
|
178
|
+
interpolate: false
|
|
178
179
|
});
|
|
179
180
|
}
|
|
180
181
|
return this.pickingFbo;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {log
|
|
1
|
+
import {Texture} from '@luma.gl/core';
|
|
2
|
+
import {log} from '@deck.gl/core';
|
|
3
3
|
|
|
4
4
|
import {terrainModule, TerrainModuleSettings} from './shader-module';
|
|
5
5
|
import {TerrainCover} from './terrain-cover';
|
|
@@ -7,7 +7,7 @@ import {TerrainPass} from './terrain-pass';
|
|
|
7
7
|
import {TerrainPickingPass, TerrainPickingPassRenderOptions} from './terrain-picking-pass';
|
|
8
8
|
import {HeightMapBuilder} from './height-map-builder';
|
|
9
9
|
|
|
10
|
-
import type {Effect, PreRenderOptions, Layer, Viewport} from '@deck.gl/core';
|
|
10
|
+
import type {Effect, EffectContext, PreRenderOptions, Layer, Viewport} from '@deck.gl/core';
|
|
11
11
|
|
|
12
12
|
/** Class to manage terrain effect */
|
|
13
13
|
export class TerrainEffect implements Effect {
|
|
@@ -28,7 +28,7 @@ export class TerrainEffect implements Effect {
|
|
|
28
28
|
/** One texture for each primitive terrain layer, into which the draped layers render */
|
|
29
29
|
private terrainCovers: Map<string, TerrainCover> = new Map();
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
setup({device, deck}: EffectContext) {
|
|
32
32
|
this.dummyHeightMap = device.createTexture({
|
|
33
33
|
width: 1,
|
|
34
34
|
height: 1,
|
|
@@ -43,21 +43,10 @@ export class TerrainEffect implements Effect {
|
|
|
43
43
|
log.warn('Terrain offset mode is not supported by this browser')();
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
deck._addDefaultShaderModule(terrainModule);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
preRender(
|
|
50
|
-
if (!this.dummyHeightMap) {
|
|
51
|
-
// First time this effect is in use, initialize resources and register the shader module
|
|
52
|
-
this.initialize(device);
|
|
53
|
-
for (const layer of opts.layers) {
|
|
54
|
-
// Force the terrain layer (and its descendents) to rebuild their models with the new shader
|
|
55
|
-
if (layer.props.operation.includes('terrain')) {
|
|
56
|
-
layer.setChangeFlags({extensionsChanged: true});
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
49
|
+
preRender(opts: PreRenderOptions): void {
|
|
61
50
|
// @ts-expect-error pickZ only defined in picking pass
|
|
62
51
|
if (opts.pickZ) {
|
|
63
52
|
// Do not update if picking attributes
|
|
@@ -106,7 +95,7 @@ export class TerrainEffect implements Effect {
|
|
|
106
95
|
};
|
|
107
96
|
}
|
|
108
97
|
|
|
109
|
-
cleanup(): void {
|
|
98
|
+
cleanup({deck}: EffectContext): void {
|
|
110
99
|
if (this.dummyHeightMap) {
|
|
111
100
|
this.dummyHeightMap.delete();
|
|
112
101
|
this.dummyHeightMap = undefined;
|
|
@@ -122,7 +111,7 @@ export class TerrainEffect implements Effect {
|
|
|
122
111
|
}
|
|
123
112
|
this.terrainCovers.clear();
|
|
124
113
|
|
|
125
|
-
|
|
114
|
+
deck._removeDefaultShaderModule(terrainModule);
|
|
126
115
|
}
|
|
127
116
|
|
|
128
117
|
private _updateHeightMap(terrainLayers: Layer[], viewport: Viewport, opts: PreRenderOptions) {
|