ol 10.1.1-dev.1724341529501 → 10.1.1-dev.1724415449548
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/ol.d.ts +4 -0
- package/dist/ol.d.ts.map +1 -1
- package/dist/ol.js +1 -1
- package/dist/ol.js.map +1 -1
- package/layer/Flow.d.ts +199 -0
- package/layer/Flow.d.ts.map +1 -0
- package/layer/Flow.js +504 -0
- package/layer/WebGLTile.d.ts +5 -1
- package/layer/WebGLTile.d.ts.map +1 -1
- package/package.json +1 -1
- package/renderer/webgl/FlowLayer.d.ts +247 -0
- package/renderer/webgl/FlowLayer.d.ts.map +1 -0
- package/renderer/webgl/FlowLayer.js +496 -0
- package/renderer/webgl/TileLayer.d.ts +7 -5
- package/renderer/webgl/TileLayer.d.ts.map +1 -1
- package/renderer/webgl/TileLayer.js +3 -3
- package/renderer/webgl/TileLayerBase.d.ts +5 -0
- package/renderer/webgl/TileLayerBase.d.ts.map +1 -1
- package/renderer/webgl/TileLayerBase.js +9 -0
- package/util.js +1 -1
- package/webgl/Buffer.d.ts +5 -1
- package/webgl/Buffer.d.ts.map +1 -1
- package/webgl/Buffer.js +12 -1
- package/webgl/Helper.d.ts +22 -5
- package/webgl/Helper.d.ts.map +1 -1
- package/webgl/Helper.js +80 -13
- package/webgl/PostProcessingPass.d.ts +3 -0
- package/webgl/PostProcessingPass.d.ts.map +1 -1
- package/webgl/PostProcessingPass.js +7 -0
package/layer/Flow.d.ts
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
export default FlowLayer;
|
|
2
|
+
export type ParsedStyle = {
|
|
3
|
+
/**
|
|
4
|
+
* The flow tile vertex shader.
|
|
5
|
+
*/
|
|
6
|
+
tileVertexShader: string;
|
|
7
|
+
/**
|
|
8
|
+
* The flow tile fragment shader.
|
|
9
|
+
*/
|
|
10
|
+
tileFragmentShader: string;
|
|
11
|
+
/**
|
|
12
|
+
* Generic texture fragment shader.
|
|
13
|
+
*/
|
|
14
|
+
textureVertexShader: string;
|
|
15
|
+
/**
|
|
16
|
+
* Generic texture fragment shader.
|
|
17
|
+
*/
|
|
18
|
+
textureFragmentShader: string;
|
|
19
|
+
/**
|
|
20
|
+
* The particle position vertex shader.
|
|
21
|
+
*/
|
|
22
|
+
particlePositionVertexShader: string;
|
|
23
|
+
/**
|
|
24
|
+
* The particle position fragment shader.
|
|
25
|
+
*/
|
|
26
|
+
particlePositionFragmentShader: string;
|
|
27
|
+
/**
|
|
28
|
+
* The particle color vertex shader.
|
|
29
|
+
*/
|
|
30
|
+
particleColorVertexShader: string;
|
|
31
|
+
/**
|
|
32
|
+
* The particle color fragment shader.
|
|
33
|
+
*/
|
|
34
|
+
particleColorFragmentShader: string;
|
|
35
|
+
};
|
|
36
|
+
export type SourceType = import("../source/DataTile.js").default;
|
|
37
|
+
/**
|
|
38
|
+
* Translates tile data to rendered pixels.
|
|
39
|
+
*/
|
|
40
|
+
export type Style = {
|
|
41
|
+
/**
|
|
42
|
+
* Style variables. Each variable must hold a number or string. These
|
|
43
|
+
* variables can be used in the `color` {@link import ("../expr/expression.js").ExpressionValue expression} using
|
|
44
|
+
* the `['var', 'varName']` operator. To update style variables, use the {@link import ("./WebGLTile.js").default#updateStyleVariables} method.
|
|
45
|
+
*/
|
|
46
|
+
variables?: {
|
|
47
|
+
[x: string]: string | number;
|
|
48
|
+
} | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* An expression applied to color values.
|
|
51
|
+
*/
|
|
52
|
+
color?: import("../expr/expression.js").ExpressionValue | undefined;
|
|
53
|
+
};
|
|
54
|
+
export type Options = {
|
|
55
|
+
/**
|
|
56
|
+
* The maximum particle speed.
|
|
57
|
+
*/
|
|
58
|
+
maxSpeed: number;
|
|
59
|
+
/**
|
|
60
|
+
* A larger factor increases the rate at which particles cross the screen.
|
|
61
|
+
*/
|
|
62
|
+
speedFactor?: number | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* The number of particles to render.
|
|
65
|
+
*/
|
|
66
|
+
particles?: number | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Style to apply to the layer.
|
|
69
|
+
*/
|
|
70
|
+
style?: Style | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* A CSS class name to set to the layer element.
|
|
73
|
+
*/
|
|
74
|
+
className?: string | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Opacity (0, 1).
|
|
77
|
+
*/
|
|
78
|
+
opacity?: number | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* Visibility.
|
|
81
|
+
*/
|
|
82
|
+
visible?: boolean | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* The bounding extent for layer rendering. The layer will not be
|
|
85
|
+
* rendered outside of this extent.
|
|
86
|
+
*/
|
|
87
|
+
extent?: import("../extent.js").Extent | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* The z-index for layer rendering. At rendering time, the layers
|
|
90
|
+
* will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed
|
|
91
|
+
* for layers that are added to the map's `layers` collection, or `Infinity` when the layer's `setMap()`
|
|
92
|
+
* method was used.
|
|
93
|
+
*/
|
|
94
|
+
zIndex?: number | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* The minimum resolution (inclusive) at which this layer will be
|
|
97
|
+
* visible.
|
|
98
|
+
*/
|
|
99
|
+
minResolution?: number | undefined;
|
|
100
|
+
/**
|
|
101
|
+
* The maximum resolution (exclusive) below which this layer will
|
|
102
|
+
* be visible.
|
|
103
|
+
*/
|
|
104
|
+
maxResolution?: number | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* The minimum view zoom level (exclusive) above which this layer will be
|
|
107
|
+
* visible.
|
|
108
|
+
*/
|
|
109
|
+
minZoom?: number | undefined;
|
|
110
|
+
/**
|
|
111
|
+
* The maximum view zoom level (inclusive) at which this layer will
|
|
112
|
+
* be visible.
|
|
113
|
+
*/
|
|
114
|
+
maxZoom?: number | undefined;
|
|
115
|
+
/**
|
|
116
|
+
* Preload. Load low-resolution tiles up to `preload` levels. `0`
|
|
117
|
+
* means no preloading.
|
|
118
|
+
*/
|
|
119
|
+
preload?: number | undefined;
|
|
120
|
+
/**
|
|
121
|
+
* Source for this layer.
|
|
122
|
+
*/
|
|
123
|
+
source?: import("../source/DataTile.js").default<import("../DataTile.js").default> | undefined;
|
|
124
|
+
/**
|
|
125
|
+
* Sets the layer as overlay on a map. The map will not manage
|
|
126
|
+
* this layer in its layers collection, and the layer will be rendered on top. This is useful for
|
|
127
|
+
* temporary layers. The standard way to add a layer to a map and have it managed by the map is to
|
|
128
|
+
* use {@link module :ol/Map~Map#addLayer}.
|
|
129
|
+
*/
|
|
130
|
+
map?: import("../Map.js").default | undefined;
|
|
131
|
+
/**
|
|
132
|
+
* Use interim tiles on error.
|
|
133
|
+
*/
|
|
134
|
+
useInterimTilesOnError?: boolean | undefined;
|
|
135
|
+
/**
|
|
136
|
+
* The internal texture cache size. This needs to be large enough to render
|
|
137
|
+
* two zoom levels worth of tiles.
|
|
138
|
+
*/
|
|
139
|
+
cacheSize?: number | undefined;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* @classdesc
|
|
143
|
+
* Experimental layer that renders particles moving through a vector field.
|
|
144
|
+
*
|
|
145
|
+
* @extends BaseTileLayer<SourceType, FlowLayerRenderer>
|
|
146
|
+
* @fires import("../render/Event.js").RenderEvent
|
|
147
|
+
*/
|
|
148
|
+
declare class FlowLayer extends BaseTileLayer<import("../source/DataTile.js").default<import("../DataTile.js").default>, FlowLayerRenderer> {
|
|
149
|
+
/**
|
|
150
|
+
* @param {Options} options Flow layer options.
|
|
151
|
+
*/
|
|
152
|
+
constructor(options: Options);
|
|
153
|
+
/**
|
|
154
|
+
* @type {Style}
|
|
155
|
+
* @private
|
|
156
|
+
*/
|
|
157
|
+
private style_;
|
|
158
|
+
/**
|
|
159
|
+
* @type {number}
|
|
160
|
+
* @private
|
|
161
|
+
*/
|
|
162
|
+
private maxSpeed_;
|
|
163
|
+
/**
|
|
164
|
+
* @type {number}
|
|
165
|
+
* @private
|
|
166
|
+
*/
|
|
167
|
+
private speedFactor_;
|
|
168
|
+
/**
|
|
169
|
+
* @type {number}
|
|
170
|
+
* @private
|
|
171
|
+
*/
|
|
172
|
+
private particles_;
|
|
173
|
+
/**
|
|
174
|
+
* @type {Object<string, (string|number)>}
|
|
175
|
+
* @private
|
|
176
|
+
*/
|
|
177
|
+
private styleVariables_;
|
|
178
|
+
/**
|
|
179
|
+
* @private
|
|
180
|
+
*/
|
|
181
|
+
private handleSourceUpdate_;
|
|
182
|
+
/**
|
|
183
|
+
* Update any variables used by the layer style and trigger a re-render.
|
|
184
|
+
* @param {Object<string, number>} variables Variables to update.
|
|
185
|
+
*/
|
|
186
|
+
updateStyleVariables(variables: {
|
|
187
|
+
[x: string]: number;
|
|
188
|
+
}): void;
|
|
189
|
+
/**
|
|
190
|
+
* Gets the sources for this layer, for a given extent and resolution.
|
|
191
|
+
* @param {import("../extent.js").Extent} extent Extent.
|
|
192
|
+
* @param {number} resolution Resolution.
|
|
193
|
+
* @return {Array<SourceType>} Sources.
|
|
194
|
+
*/
|
|
195
|
+
getSources(extent: import("../extent.js").Extent, resolution: number): Array<SourceType>;
|
|
196
|
+
}
|
|
197
|
+
import FlowLayerRenderer from '../renderer/webgl/FlowLayer.js';
|
|
198
|
+
import BaseTileLayer from './BaseTile.js';
|
|
199
|
+
//# sourceMappingURL=Flow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Flow.d.ts","sourceRoot":"","sources":["Flow.js"],"names":[],"mappings":";;;;;sBAuRc,MAAM;;;;wBACN,MAAM;;;;yBACN,MAAM;;;;2BACN,MAAM;;;;kCACN,MAAM;;;;oCACN,MAAM;;;;+BACN,MAAM;;;;iCACN,MAAM;;yBA9QP,OAAO,uBAAuB,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;cAetC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8WpB;;;;;;GAMG;AACH;IACE;;OAEG;IACH,qBAFW,OAAO,EA2CjB;IAlCC;;;OAGG;IACH,eAAiC;IAKjC;;;OAGG;IACH,kBAAiC;IAEjC;;;OAGG;IACH,qBAAuC;IAEvC;;;OAGG;IACH,mBAAmC;IAEnC;;;OAGG;IACH,wBAAkD;IAKpD;;OAEG;IACH,4BAIC;IAED;;;OAGG;IACH,gCAFW;YAAO,MAAM,GAAE,MAAM;KAAC,QAKhC;IAED;;;;;OAKG;IACH,mBAJW,OAAO,cAAc,EAAE,MAAM,cAC7B,MAAM,GACL,KAAK,CAAC,UAAU,CAAC,CAM5B;CAgBF;8BA3ewC,gCAAgC;0BAD/C,eAAe"}
|
package/layer/Flow.js
ADDED
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module ol/layer/Flow
|
|
3
|
+
*/
|
|
4
|
+
import BaseTileLayer from './BaseTile.js';
|
|
5
|
+
import FlowLayerRenderer, {A, U, V} from '../renderer/webgl/FlowLayer.js';
|
|
6
|
+
import LayerProperty from './Property.js';
|
|
7
|
+
import {Attributes as BA, Uniforms as BU} from '../renderer/webgl/TileLayer.js';
|
|
8
|
+
import {ColorType} from '../expr/expression.js';
|
|
9
|
+
import {expressionToGlsl} from '../webgl/styleparser.js';
|
|
10
|
+
import {
|
|
11
|
+
getStringNumberEquivalent,
|
|
12
|
+
newCompilationContext,
|
|
13
|
+
uniformNameForVariable,
|
|
14
|
+
} from '../expr/gpu.js';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {import("../source/DataTile.js").default} SourceType
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {Object} Style
|
|
22
|
+
* Translates tile data to rendered pixels.
|
|
23
|
+
*
|
|
24
|
+
* @property {Object<string, (string|number)>} [variables] Style variables. Each variable must hold a number or string. These
|
|
25
|
+
* variables can be used in the `color` {@link import("../expr/expression.js").ExpressionValue expression} using
|
|
26
|
+
* the `['var', 'varName']` operator. To update style variables, use the {@link import("./WebGLTile.js").default#updateStyleVariables} method.
|
|
27
|
+
* @property {import("../expr/expression.js").ExpressionValue} [color] An expression applied to color values.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @typedef {Object} Options
|
|
32
|
+
* @property {number} maxSpeed The maximum particle speed.
|
|
33
|
+
* @property {number} [speedFactor=0.001] A larger factor increases the rate at which particles cross the screen.
|
|
34
|
+
* @property {number} [particles=65536] The number of particles to render.
|
|
35
|
+
* @property {Style} [style] Style to apply to the layer.
|
|
36
|
+
* @property {string} [className='ol-layer'] A CSS class name to set to the layer element.
|
|
37
|
+
* @property {number} [opacity=1] Opacity (0, 1).
|
|
38
|
+
* @property {boolean} [visible=true] Visibility.
|
|
39
|
+
* @property {import("../extent.js").Extent} [extent] The bounding extent for layer rendering. The layer will not be
|
|
40
|
+
* rendered outside of this extent.
|
|
41
|
+
* @property {number} [zIndex] The z-index for layer rendering. At rendering time, the layers
|
|
42
|
+
* will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed
|
|
43
|
+
* for layers that are added to the map's `layers` collection, or `Infinity` when the layer's `setMap()`
|
|
44
|
+
* method was used.
|
|
45
|
+
* @property {number} [minResolution] The minimum resolution (inclusive) at which this layer will be
|
|
46
|
+
* visible.
|
|
47
|
+
* @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will
|
|
48
|
+
* be visible.
|
|
49
|
+
* @property {number} [minZoom] The minimum view zoom level (exclusive) above which this layer will be
|
|
50
|
+
* visible.
|
|
51
|
+
* @property {number} [maxZoom] The maximum view zoom level (inclusive) at which this layer will
|
|
52
|
+
* be visible.
|
|
53
|
+
* @property {number} [preload=0] Preload. Load low-resolution tiles up to `preload` levels. `0`
|
|
54
|
+
* means no preloading.
|
|
55
|
+
* @property {SourceType} [source] Source for this layer.
|
|
56
|
+
* @property {import("../Map.js").default} [map] Sets the layer as overlay on a map. The map will not manage
|
|
57
|
+
* this layer in its layers collection, and the layer will be rendered on top. This is useful for
|
|
58
|
+
* temporary layers. The standard way to add a layer to a map and have it managed by the map is to
|
|
59
|
+
* use {@link module:ol/Map~Map#addLayer}.
|
|
60
|
+
* @property {boolean} [useInterimTilesOnError=true] Use interim tiles on error.
|
|
61
|
+
* @property {number} [cacheSize=512] The internal texture cache size. This needs to be large enough to render
|
|
62
|
+
* two zoom levels worth of tiles.
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
const tileVertexShader = `
|
|
66
|
+
attribute vec2 ${BA.TEXTURE_COORD};
|
|
67
|
+
uniform mat4 ${BU.TILE_TRANSFORM};
|
|
68
|
+
uniform float ${BU.TEXTURE_PIXEL_WIDTH};
|
|
69
|
+
uniform float ${BU.TEXTURE_PIXEL_HEIGHT};
|
|
70
|
+
uniform float ${BU.TEXTURE_RESOLUTION};
|
|
71
|
+
uniform float ${BU.TEXTURE_ORIGIN_X};
|
|
72
|
+
uniform float ${BU.TEXTURE_ORIGIN_Y};
|
|
73
|
+
uniform float ${BU.DEPTH};
|
|
74
|
+
|
|
75
|
+
varying vec2 v_textureCoord;
|
|
76
|
+
varying vec2 v_mapCoord;
|
|
77
|
+
|
|
78
|
+
void main() {
|
|
79
|
+
v_textureCoord = ${BA.TEXTURE_COORD};
|
|
80
|
+
v_mapCoord = vec2(
|
|
81
|
+
${BU.TEXTURE_ORIGIN_X} + ${BU.TEXTURE_RESOLUTION} * ${BU.TEXTURE_PIXEL_WIDTH} * v_textureCoord[0],
|
|
82
|
+
${BU.TEXTURE_ORIGIN_Y} - ${BU.TEXTURE_RESOLUTION} * ${BU.TEXTURE_PIXEL_HEIGHT} * v_textureCoord[1]
|
|
83
|
+
);
|
|
84
|
+
gl_Position = ${BU.TILE_TRANSFORM} * vec4(${BA.TEXTURE_COORD}, ${BU.DEPTH}, 1.0);
|
|
85
|
+
}
|
|
86
|
+
`;
|
|
87
|
+
|
|
88
|
+
const tileFragmentShader = `
|
|
89
|
+
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
|
90
|
+
precision highp float;
|
|
91
|
+
#else
|
|
92
|
+
precision mediump float;
|
|
93
|
+
#endif
|
|
94
|
+
|
|
95
|
+
uniform vec4 ${BU.RENDER_EXTENT};
|
|
96
|
+
uniform float ${U.MAX_SPEED};
|
|
97
|
+
uniform sampler2D ${BU.TILE_TEXTURE_ARRAY}[1];
|
|
98
|
+
|
|
99
|
+
varying vec2 v_textureCoord;
|
|
100
|
+
varying vec2 v_mapCoord;
|
|
101
|
+
|
|
102
|
+
void main() {
|
|
103
|
+
if (
|
|
104
|
+
v_mapCoord[0] < ${BU.RENDER_EXTENT}[0] ||
|
|
105
|
+
v_mapCoord[1] < ${BU.RENDER_EXTENT}[1] ||
|
|
106
|
+
v_mapCoord[0] > ${BU.RENDER_EXTENT}[2] ||
|
|
107
|
+
v_mapCoord[1] > ${BU.RENDER_EXTENT}[3]
|
|
108
|
+
) {
|
|
109
|
+
discard;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
vec4 velocity = texture2D(${BU.TILE_TEXTURE_ARRAY}[0], v_textureCoord);
|
|
113
|
+
gl_FragColor = vec4((velocity.xy + ${U.MAX_SPEED}) / (2.0 * ${U.MAX_SPEED}), 0, 1);
|
|
114
|
+
}
|
|
115
|
+
`;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Sets up a varying position for rendering textures.
|
|
119
|
+
*/
|
|
120
|
+
const quadVertexShader = `
|
|
121
|
+
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
|
122
|
+
precision highp float;
|
|
123
|
+
#else
|
|
124
|
+
precision mediump float;
|
|
125
|
+
#endif
|
|
126
|
+
|
|
127
|
+
attribute vec2 ${A.POSITION};
|
|
128
|
+
|
|
129
|
+
varying vec2 ${V.POSITION};
|
|
130
|
+
|
|
131
|
+
void main() {
|
|
132
|
+
${V.POSITION} = ${A.POSITION};
|
|
133
|
+
gl_Position = vec4(1.0 - 2.0 * ${A.POSITION}, 0, 1);
|
|
134
|
+
}
|
|
135
|
+
`;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Sampes a texture and renders it with a new opacity.
|
|
139
|
+
*/
|
|
140
|
+
const textureFragmentShader = `
|
|
141
|
+
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
|
142
|
+
precision highp float;
|
|
143
|
+
#else
|
|
144
|
+
precision mediump float;
|
|
145
|
+
#endif
|
|
146
|
+
|
|
147
|
+
uniform sampler2D ${U.TEXTURE};
|
|
148
|
+
uniform float ${U.OPACITY};
|
|
149
|
+
|
|
150
|
+
varying vec2 ${V.POSITION};
|
|
151
|
+
|
|
152
|
+
void main() {
|
|
153
|
+
vec4 color = texture2D(${U.TEXTURE}, 1.0 - ${V.POSITION});
|
|
154
|
+
gl_FragColor = vec4(floor(255.0 * color * ${U.OPACITY}) / 255.0);
|
|
155
|
+
}
|
|
156
|
+
`;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Samples current particle positions, determines new positions based on velocity, and
|
|
160
|
+
* encodes the new position as a color.
|
|
161
|
+
*/
|
|
162
|
+
const particlePositionFragmentShader = `
|
|
163
|
+
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
|
164
|
+
precision highp float;
|
|
165
|
+
#else
|
|
166
|
+
precision mediump float;
|
|
167
|
+
#endif
|
|
168
|
+
|
|
169
|
+
uniform sampler2D ${U.POSITION_TEXTURE};
|
|
170
|
+
uniform sampler2D ${U.VELOCITY_TEXTURE};
|
|
171
|
+
uniform float ${U.RANDOM_SEED};
|
|
172
|
+
uniform float ${U.SPEED_FACTOR};
|
|
173
|
+
uniform float ${U.DROP_RATE};
|
|
174
|
+
uniform float ${U.DROP_RATE_BUMP};
|
|
175
|
+
uniform vec2 ${U.ROTATION};
|
|
176
|
+
uniform vec2 ${U.VIEWPORT_SIZE_PX};
|
|
177
|
+
|
|
178
|
+
varying vec2 ${V.POSITION};
|
|
179
|
+
|
|
180
|
+
// pseudo-random generator
|
|
181
|
+
const vec3 randConstants = vec3(12.9898, 78.233, 4375.85453);
|
|
182
|
+
|
|
183
|
+
float rand(const vec2 co) {
|
|
184
|
+
float t = dot(randConstants.xy, co);
|
|
185
|
+
return fract(sin(t) * (randConstants.z + t));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
void main() {
|
|
189
|
+
vec4 positionColor = texture2D(${U.POSITION_TEXTURE}, ${V.POSITION});
|
|
190
|
+
|
|
191
|
+
// decode particle position from pixel RGBA
|
|
192
|
+
vec2 particlePosition = vec2(
|
|
193
|
+
positionColor.r / 255.0 + positionColor.b,
|
|
194
|
+
positionColor.g / 255.0 + positionColor.a
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
vec4 velocityColor = texture2D(${U.VELOCITY_TEXTURE}, particlePosition);
|
|
198
|
+
if (velocityColor.a == 0.0) {
|
|
199
|
+
discard;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
float vx = 2.0 * velocityColor.r - 1.0;
|
|
203
|
+
float vy = 2.0 * velocityColor.g - 1.0;
|
|
204
|
+
|
|
205
|
+
// normalized veloicty (magnitude 0 - 1)
|
|
206
|
+
vec2 velocity = vec2(
|
|
207
|
+
vx * ${U.ROTATION}.x - vy * ${U.ROTATION}.y,
|
|
208
|
+
vx * ${U.ROTATION}.y + vy * ${U.ROTATION}.x
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
// account for aspect ratio (square particle position texture, non-square map)
|
|
212
|
+
float aspectRatio = ${U.VIEWPORT_SIZE_PX}.x / ${U.VIEWPORT_SIZE_PX}.y;
|
|
213
|
+
vec2 offset = vec2(velocity.x / aspectRatio, velocity.y) * ${U.SPEED_FACTOR};
|
|
214
|
+
|
|
215
|
+
// update particle position, wrapping around the edge
|
|
216
|
+
particlePosition = fract(1.0 + particlePosition + offset);
|
|
217
|
+
|
|
218
|
+
// a random seed to use for the particle drop
|
|
219
|
+
vec2 seed = (particlePosition + ${V.POSITION}) * ${U.RANDOM_SEED};
|
|
220
|
+
|
|
221
|
+
// drop rate is a chance a particle will restart at random position, to avoid degeneration
|
|
222
|
+
float dropRate = ${U.DROP_RATE} + length(velocity) * ${U.DROP_RATE_BUMP};
|
|
223
|
+
float drop = step(1.0 - dropRate, rand(seed));
|
|
224
|
+
|
|
225
|
+
vec2 randomPosition = vec2(rand(seed + 1.3), rand(seed + 2.1));
|
|
226
|
+
particlePosition = mix(particlePosition, randomPosition, drop);
|
|
227
|
+
|
|
228
|
+
// encode the new particle position back into RGBA
|
|
229
|
+
gl_FragColor = vec4(
|
|
230
|
+
fract(particlePosition * 255.0),
|
|
231
|
+
floor(particlePosition * 255.0) / 255.0
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
`;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Samples the particle position texture to decode the particle position
|
|
238
|
+
* based on pixel color.
|
|
239
|
+
*/
|
|
240
|
+
const particleColorVertexShader = `
|
|
241
|
+
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
|
242
|
+
precision highp float;
|
|
243
|
+
#else
|
|
244
|
+
precision mediump float;
|
|
245
|
+
#endif
|
|
246
|
+
|
|
247
|
+
attribute float ${A.INDEX};
|
|
248
|
+
|
|
249
|
+
uniform sampler2D ${U.POSITION_TEXTURE};
|
|
250
|
+
uniform float ${U.PARTICLE_COUNT_SQRT};
|
|
251
|
+
|
|
252
|
+
varying vec2 ${V.POSITION};
|
|
253
|
+
|
|
254
|
+
void main() {
|
|
255
|
+
vec4 color = texture2D(
|
|
256
|
+
${U.POSITION_TEXTURE},
|
|
257
|
+
vec2(
|
|
258
|
+
fract(${A.INDEX} / ${U.PARTICLE_COUNT_SQRT}),
|
|
259
|
+
floor(${A.INDEX} / ${U.PARTICLE_COUNT_SQRT}) / ${U.PARTICLE_COUNT_SQRT}
|
|
260
|
+
)
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
${V.POSITION} = vec2(
|
|
264
|
+
color.r / 255.0 + color.b,
|
|
265
|
+
color.g / 255.0 + color.a
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
gl_PointSize = 1.0;
|
|
269
|
+
gl_Position = vec4(
|
|
270
|
+
2.0 * ${V.POSITION}.x - 1.0,
|
|
271
|
+
2.0 * ${V.POSITION}.y - 1.0,
|
|
272
|
+
0,
|
|
273
|
+
1
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
`;
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* @typedef {Object} ParsedStyle
|
|
280
|
+
* @property {string} tileVertexShader The flow tile vertex shader.
|
|
281
|
+
* @property {string} tileFragmentShader The flow tile fragment shader.
|
|
282
|
+
* @property {string} textureVertexShader Generic texture fragment shader.
|
|
283
|
+
* @property {string} textureFragmentShader Generic texture fragment shader.
|
|
284
|
+
* @property {string} particlePositionVertexShader The particle position vertex shader.
|
|
285
|
+
* @property {string} particlePositionFragmentShader The particle position fragment shader.
|
|
286
|
+
* @property {string} particleColorVertexShader The particle color vertex shader.
|
|
287
|
+
* @property {string} particleColorFragmentShader The particle color fragment shader.
|
|
288
|
+
*/
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* @param {Style} style The layer style.
|
|
292
|
+
* @return {ParsedStyle} Shaders and uniforms generated from the style.
|
|
293
|
+
*/
|
|
294
|
+
function parseStyle(style) {
|
|
295
|
+
const context = newCompilationContext();
|
|
296
|
+
context.inFragmentShader = true;
|
|
297
|
+
const pipeline = [];
|
|
298
|
+
|
|
299
|
+
if (style.color !== undefined) {
|
|
300
|
+
const color = expressionToGlsl(context, style.color, ColorType);
|
|
301
|
+
pipeline.push(`color = ${color};`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const variableNames = Object.keys(context.variables);
|
|
305
|
+
if (variableNames.length > 1 && !style.variables) {
|
|
306
|
+
throw new Error(
|
|
307
|
+
`Missing variables in style (expected ${context.variables})`,
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/** @type {Object<string,import("../webgl/Helper").UniformValue>} */
|
|
312
|
+
const uniforms = {};
|
|
313
|
+
|
|
314
|
+
for (const variableName of variableNames) {
|
|
315
|
+
if (!(variableName in style.variables)) {
|
|
316
|
+
throw new Error(`Missing '${variableName}' in style variables`);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const uniformName = uniformNameForVariable(variableName);
|
|
320
|
+
uniforms[uniformName] = function () {
|
|
321
|
+
let value = style.variables[variableName];
|
|
322
|
+
if (typeof value === 'string') {
|
|
323
|
+
value = getStringNumberEquivalent(value);
|
|
324
|
+
}
|
|
325
|
+
return value !== undefined ? value : -9999999; // to avoid matching with the first string literal
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const uniformDeclarations = Object.keys(uniforms).map(function (name) {
|
|
330
|
+
return `uniform float ${name};`;
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
const functionDefintions = Object.keys(context.functions).map(
|
|
334
|
+
function (name) {
|
|
335
|
+
return context.functions[name];
|
|
336
|
+
},
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
const particleColorFragmentShader = `
|
|
340
|
+
#ifdef GL_FRAGMENT_PRECISION_HIGH
|
|
341
|
+
precision highp float;
|
|
342
|
+
#else
|
|
343
|
+
precision mediump float;
|
|
344
|
+
#endif
|
|
345
|
+
|
|
346
|
+
uniform sampler2D ${U.VELOCITY_TEXTURE};
|
|
347
|
+
uniform float ${U.MAX_SPEED};
|
|
348
|
+
uniform vec2 ${U.ROTATION};
|
|
349
|
+
|
|
350
|
+
${uniformDeclarations.join('\n')}
|
|
351
|
+
|
|
352
|
+
varying vec2 ${V.POSITION};
|
|
353
|
+
|
|
354
|
+
${functionDefintions.join('\n')}
|
|
355
|
+
|
|
356
|
+
void main() {
|
|
357
|
+
vec4 velocityColor = texture2D(${U.VELOCITY_TEXTURE}, ${V.POSITION});
|
|
358
|
+
|
|
359
|
+
float vx = mix(-${U.MAX_SPEED}, ${U.MAX_SPEED}, velocityColor.r);
|
|
360
|
+
float vy = mix(-${U.MAX_SPEED}, ${U.MAX_SPEED}, velocityColor.g);
|
|
361
|
+
|
|
362
|
+
vec2 velocity = vec2(
|
|
363
|
+
vx * ${U.ROTATION}.x - vy * ${U.ROTATION}.y,
|
|
364
|
+
vx * ${U.ROTATION}.y + vy * ${U.ROTATION}.x
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
float v_prop_speed = length(velocity);
|
|
368
|
+
|
|
369
|
+
vec4 color;
|
|
370
|
+
|
|
371
|
+
${pipeline.join('\n')}
|
|
372
|
+
|
|
373
|
+
if (color.a == 0.0) {
|
|
374
|
+
discard;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
gl_FragColor = color;
|
|
378
|
+
}
|
|
379
|
+
`;
|
|
380
|
+
|
|
381
|
+
return {
|
|
382
|
+
tileVertexShader,
|
|
383
|
+
tileFragmentShader,
|
|
384
|
+
particleColorVertexShader,
|
|
385
|
+
particleColorFragmentShader,
|
|
386
|
+
particlePositionVertexShader: quadVertexShader,
|
|
387
|
+
particlePositionFragmentShader,
|
|
388
|
+
textureVertexShader: quadVertexShader,
|
|
389
|
+
textureFragmentShader,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* @type {Array<SourceType>}
|
|
395
|
+
*/
|
|
396
|
+
const sources = [];
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* @classdesc
|
|
400
|
+
* Experimental layer that renders particles moving through a vector field.
|
|
401
|
+
*
|
|
402
|
+
* @extends BaseTileLayer<SourceType, FlowLayerRenderer>
|
|
403
|
+
* @fires import("../render/Event.js").RenderEvent
|
|
404
|
+
*/
|
|
405
|
+
class FlowLayer extends BaseTileLayer {
|
|
406
|
+
/**
|
|
407
|
+
* @param {Options} options Flow layer options.
|
|
408
|
+
*/
|
|
409
|
+
constructor(options) {
|
|
410
|
+
const baseOptions = Object.assign({}, options);
|
|
411
|
+
delete baseOptions.maxSpeed;
|
|
412
|
+
delete baseOptions.speedFactor;
|
|
413
|
+
delete baseOptions.particles;
|
|
414
|
+
super(baseOptions);
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* @type {Style}
|
|
418
|
+
* @private
|
|
419
|
+
*/
|
|
420
|
+
this.style_ = options.style || {};
|
|
421
|
+
|
|
422
|
+
if (!(options.maxSpeed > 0)) {
|
|
423
|
+
throw new Error('maxSpeed is required');
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* @type {number}
|
|
427
|
+
* @private
|
|
428
|
+
*/
|
|
429
|
+
this.maxSpeed_ = options.maxSpeed;
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* @type {number}
|
|
433
|
+
* @private
|
|
434
|
+
*/
|
|
435
|
+
this.speedFactor_ = options.speedFactor;
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* @type {number}
|
|
439
|
+
* @private
|
|
440
|
+
*/
|
|
441
|
+
this.particles_ = options.particles;
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* @type {Object<string, (string|number)>}
|
|
445
|
+
* @private
|
|
446
|
+
*/
|
|
447
|
+
this.styleVariables_ = this.style_.variables || {};
|
|
448
|
+
|
|
449
|
+
this.addChangeListener(LayerProperty.SOURCE, this.handleSourceUpdate_);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* @private
|
|
454
|
+
*/
|
|
455
|
+
handleSourceUpdate_() {
|
|
456
|
+
if (this.hasRenderer()) {
|
|
457
|
+
this.getRenderer().clearCache();
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Update any variables used by the layer style and trigger a re-render.
|
|
463
|
+
* @param {Object<string, number>} variables Variables to update.
|
|
464
|
+
*/
|
|
465
|
+
updateStyleVariables(variables) {
|
|
466
|
+
Object.assign(this.styleVariables_, variables);
|
|
467
|
+
this.changed();
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Gets the sources for this layer, for a given extent and resolution.
|
|
472
|
+
* @param {import("../extent.js").Extent} extent Extent.
|
|
473
|
+
* @param {number} resolution Resolution.
|
|
474
|
+
* @return {Array<SourceType>} Sources.
|
|
475
|
+
*/
|
|
476
|
+
getSources(extent, resolution) {
|
|
477
|
+
const source = this.getSource();
|
|
478
|
+
sources[0] = source;
|
|
479
|
+
return sources;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* @override
|
|
484
|
+
*/
|
|
485
|
+
createRenderer() {
|
|
486
|
+
const parsedStyle = parseStyle(this.style_);
|
|
487
|
+
|
|
488
|
+
return new FlowLayerRenderer(this, {
|
|
489
|
+
...parsedStyle,
|
|
490
|
+
cacheSize: this.getCacheSize(),
|
|
491
|
+
maxSpeed: this.maxSpeed_,
|
|
492
|
+
speedFactor: this.speedFactor_,
|
|
493
|
+
particles: this.particles_,
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Clean up underlying WebGL resources.
|
|
500
|
+
* @function
|
|
501
|
+
*/
|
|
502
|
+
FlowLayer.prototype.dispose;
|
|
503
|
+
|
|
504
|
+
export default FlowLayer;
|