@pirireis/webglobeplugins 0.6.32-a → 0.6.34

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.
@@ -19,7 +19,7 @@ const constraintFloat = (x, lowerBound, upperBound) => {
19
19
  }
20
20
 
21
21
 
22
- export default class Plugin {
22
+ export default class BearingLinePlugin {
23
23
  /**
24
24
  * @param {*} id
25
25
  * @param {Map<[key, ContextTextWriter3]>} textWritersMap
@@ -131,6 +131,7 @@ export class CircleLineChainPlugin {
131
131
  updateText(textWriterIDs) {
132
132
  const chainKeyIterator = this._chainListMap.getAllChainKeysIterator();
133
133
  this._updateTexts(chainKeyIterator, textWriterIDs);
134
+ this.globe.DrawRender();
134
135
  }
135
136
 
136
137
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pirireis/webglobeplugins",
3
- "version": "0.6.32-a",
3
+ "version": "0.6.34",
4
4
  "main": "index.js",
5
5
  "author": "Toprak Nihat Deniz Ozturk",
6
6
  "license": "MIT"
@@ -0,0 +1,80 @@
1
+ import { latLongToPixelXY } from "../util";
2
+
3
+
4
+
5
+ /**
6
+ * @param {Array.<Array.<number>>} coordinates
7
+ * @param {Array.<number>} timestamps
8
+ * @param {Array.<String>} styleGroupNameArray
9
+ * @param {Object.<string, TrackStyleGroup>} _groupColorMap
10
+ * @param {Float32Array} floatArray
11
+ * @param {number} offset
12
+ *
13
+ * create floatArray with createFloat32Array before calling this function.
14
+ * start offset from 0.
15
+ * feed the floatArray with a track data and offset that is returned from the previous call.
16
+ */
17
+ function featuresToLineStringData(data) {
18
+ /**
19
+ * features are the tracks
20
+ * feature[i].geometry.coordinates are the points of the track
21
+ * feature[i].properties.messageTime are the timestamps of the points
22
+ *
23
+ */
24
+ const features = data.features;
25
+ let size = data.features.length - 1;
26
+
27
+ let startTime = features[0].properties.messageTime[0];
28
+ let endTime = features[0].properties.messageTime[features[0].properties.messageTime.length - 1];
29
+
30
+ for (let feature of features) {
31
+ size += feature.properties.messageTime.length;
32
+ startTime = Math.min(startTime, feature.properties.messageTime[0]);
33
+ endTime = Math.max(endTime, feature.properties.messageTime[feature.properties.messageTime.length - 1]);
34
+ }
35
+ const array = new Float32Array(size * 9);
36
+ let offset = 0;
37
+
38
+ {
39
+ const feature = features[0];
40
+ const coordinates = feature.geometry.coordinates;
41
+ const timestamps = feature.properties.messageTime.map((time) => (time - startTime) / 1000);
42
+ offset = fillSliceOfFloat32ArrayLineStrip(array, offset, coordinates, timestamps);
43
+ }
44
+ for (let i = 1; i < features.length; i++) {
45
+ const feature = features[i];
46
+ const coordinates = feature.geometry.coordinates;
47
+ const timestamps = feature.properties.messageTime.map((time) => (time - startTime) / 1000);
48
+ offset = addCuttingPointLineStrip(array, offset);
49
+ offset = fillSliceOfFloat32ArrayLineStrip(array, offset, coordinates, timestamps);
50
+ }
51
+
52
+ return { data: array, startTime, endTime };
53
+ }
54
+
55
+
56
+ function fillSliceOfFloat32ArrayLineStrip(floatArray, offset, coordinates, timestamps, { styleGroupNameArray = null, groupColorFunction = () => [Math.random(), Math.random(), Math.random()] } = {}) {
57
+ const startTime = timestamps[0];
58
+ const endTime = timestamps[timestamps.length - 1];
59
+ for (let i = 0; i < coordinates.length; i++) {
60
+ const time = timestamps[i];
61
+ const coord = coordinates[i];
62
+ const styleGroupName = styleGroupNameArray ? styleGroupNameArray[i] : "default";
63
+ const { x, y } = latLongToPixelXY(coord[1], coord[0]);
64
+ const z = coord[2] ? coord[2] / 1000.0 : 0;
65
+ floatArray.set([x, y, z, time, ...groupColorFunction(styleGroupName), startTime, endTime], offset);
66
+ offset += 9;
67
+ }
68
+ return offset;
69
+ }
70
+
71
+ function addCuttingPointLineStrip(floatArray, offset) {
72
+ floatArray.set([0, 0, 0, 0, -1.0, -1.0, -1.0, 0, 0], offset);
73
+ return offset + 9;
74
+ }
75
+
76
+
77
+
78
+
79
+
80
+ export { addCuttingPointLineStrip, featuresToLineStringData, fillSliceOfFloat32ArrayLineStrip, latLongToPixelXY };
@@ -1,3 +1,6 @@
1
1
  import TimeTracks from './plugin';
2
2
  import { Adaptor, fillSliceOfFloat32Array, createFloat32Array } from './adaptors';
3
- export { Adaptor, fillSliceOfFloat32Array, createFloat32Array, TimeTracks };
3
+
4
+ import TimeTracksLineStrip from './plugin-line-strip';
5
+ import { addCuttingPointLineStrip, featuresToLineStringData, fillSliceOfFloat32ArrayLineStrip, latLongToPixelXY } from './adaptors-line-strip';
6
+ export { Adaptor, fillSliceOfFloat32Array, createFloat32Array, TimeTracks, TimeTracksLineStrip, addCuttingPointLineStrip, featuresToLineStringData, fillSliceOfFloat32ArrayLineStrip, latLongToPixelXY };
@@ -0,0 +1,307 @@
1
+ /**
2
+ * Author: Toprak Nihat Deniz Ozturk
3
+ */
4
+
5
+
6
+
7
+ import TrackGlowLineProgram from './program-line-strip';
8
+ import PointProgram from './programpoint-line-strip';
9
+
10
+ /**
11
+ * @typedef {Float32Array} TimeTrackMultiColorData | A linestring is representation, let A{a1, a2, a3}, B{b1, b2} be the points of the line.
12
+ * TimeTrackMultiColorData is [
13
+ * a1x, a1y, a1z, a1time, a1r, a1g, a1b, a1time, a3time,
14
+ * a2x, a2y, a2z, a2time, a2r, a2g, a2b, a1time, a3time,
15
+ * a3x, a3y, a3z, a3time, a3r, a3g, a3b, a1time, a3time,
16
+ * 0, 0, 0, 0, -1, -1, -1, 0, 0,
17
+ * b1x, b1y, b1z, b1time, b1r, b1g, b1b, b1time, b2time,
18
+ * b2x, b2y, b2z, b2time, b2r, b2g, b2b, BstartTime, BendTime
19
+ * ]
20
+ * there is a cutting point between A and B
21
+ *
22
+ */
23
+
24
+
25
+
26
+
27
+
28
+ /**
29
+ * Access following methods through `plugin.program.` :
30
+ * * setGamma
31
+ * * setExposure
32
+ * * setAlphaThreshold
33
+ * * setWeights
34
+ * * setHeadPercentage
35
+ * * setRouteAlpha
36
+ * * setFinalAlphaRatio
37
+
38
+ uses float32array in a * {@link TimeTrackMultiColorData} format
39
+
40
+ */
41
+ export default class TimeTrackMultiColorPlugin {
42
+ /**
43
+ * @param {String} id
44
+ * @param {Object} options
45
+ * @param {TimeTrackMultiColorData} options.data {@link TimeTrackMultiColorData}
46
+ * @param {number} options.headPercentage 0 ~ 1
47
+ * @param {number} options.routeAlpha 0 ~ 1
48
+ * @param {Array.<Number>} options.weights [w1, w2, w3, w4, w5]
49
+ * @param {number} options.alphaThreshold 0 ~ 1
50
+ * @param {number} options.exposure 0 ~ inf
51
+ * @param {number} options.gamma 0 ~ inf
52
+ * @param {number} options.finalAlphaRatio 0 ~ 1
53
+ * @param {number} pointOptions.opacity 0 ~ 1
54
+ * @param {number} pointOptions.pointSize 0 ~ inf
55
+ * @param {boolean} pointOptions.isOn true | false
56
+ */
57
+ constructor(id, options = {}, { opacity = 1.0, pointSize = 1, isOn = false } = {}) {
58
+ this.id = id;
59
+
60
+ this.globe = null;
61
+ this.gl = null;
62
+ this.program = null;
63
+ this._headTime = 0;
64
+ this._tailTime = 0;
65
+
66
+ this._data = options.data || null;
67
+ this._options = options;
68
+ this._pointOptions = { opacity, pointSize, isOn };
69
+ this.program = null;
70
+
71
+ this._transporArr = new Float32Array(3);
72
+
73
+ this._ready = false;
74
+
75
+ this.pointProgram = null;
76
+
77
+ this._attrBuffer = null;
78
+ }
79
+
80
+ // ----------------------------------
81
+ // --- user methods ---
82
+ // ----------------------------------
83
+
84
+ setHeadAndTailTime(headTime, tailTime) {
85
+ this._headTime = headTime;
86
+ this._tailTime = tailTime;
87
+ // console.log("setHeadAndTailTime", headTime, tailTime);
88
+ this.pointProgram?.setHeadTime(headTime);
89
+ this.globe.DrawRender();
90
+ }
91
+
92
+ setGlow(isGlow) {
93
+ this.program.setGlow(isGlow);
94
+ this.globe.DrawRender();
95
+ }
96
+
97
+ setPremultipliedAlpha(isPremultiplied) {
98
+ this.program.setPremultipliedAlpha(isPremultiplied);
99
+ this.globe.DrawRender();
100
+ }
101
+
102
+ setBlurWeights(weights) {
103
+ this.program.setBlurWeights(weights);
104
+ this.globe.DrawRender();
105
+ }
106
+
107
+ setHeadPercentage(headPercentage) {
108
+ this.program.setHeadPercentage(headPercentage);
109
+ this.globe.DrawRender();
110
+ }
111
+
112
+ setRouteAlpha(routeAlpha) {
113
+ this.program.setRouteAlpha(routeAlpha);
114
+ this.globe.DrawRender();
115
+ }
116
+
117
+ setFinalAlphaRatio(finalAlphaRatio) {
118
+ this.program.setFinalAlphaRatio(finalAlphaRatio);
119
+ this.globe.DrawRender();
120
+ }
121
+
122
+ setGamma(gamma) {
123
+ this.program.setGamma(gamma);
124
+ this.globe.DrawRender();
125
+ }
126
+
127
+ setExposure(exposure) {
128
+ this.program.setExposure(exposure);
129
+ this.globe.DrawRender();
130
+ }
131
+
132
+ setBlurRepetition(repetition) {
133
+ this.program.setBlurRepetition(repetition);
134
+ this.globe.DrawRender();
135
+ }
136
+
137
+ setAlphaThreshold(alphaThreshold) {
138
+ this.program.setAlphaThreshold(alphaThreshold);
139
+ this.globe.DrawRender();
140
+ }
141
+
142
+ // ---------------point program setters-------------------
143
+
144
+ setPointOpacity(opacity) {
145
+ this._pointOptions.opacity = opacity;
146
+ if (this.pointProgram) {
147
+ this.pointProgram.setOpacity(opacity);
148
+ this.globe.DrawRender();
149
+ }
150
+ }
151
+
152
+ setPointSize(size) {
153
+ this._pointOptions.pointSize = size;
154
+ if (this.pointProgram) {
155
+ this.pointProgram.setPointSize(size);
156
+ this.globe.DrawRender();
157
+ }
158
+ }
159
+
160
+ pointSwitch(isOn) {
161
+ if (isOn && !this.pointProgram) {
162
+ this.pointProgram = this._createPointProgram();
163
+ } else {
164
+ this._deletePointProgram();
165
+ }
166
+
167
+ }
168
+
169
+ // ------------------------------------------------------------
170
+
171
+ _createPointProgram() {
172
+ const { gl } = this;
173
+ const program = new PointProgram(gl, this.globe, this._attrBuffer, this._pointOptions);
174
+ program.setDrawCount(this._totalSize);
175
+ return program;
176
+ }
177
+
178
+ _deletePointProgram() {
179
+ if (this.pointProgram) this.pointProgram.free();
180
+ this.pointProgram = null;
181
+ }
182
+
183
+ // -------------------------------------------------------------
184
+
185
+ isReady() {
186
+ return this._ready;
187
+ }
188
+
189
+ /**
190
+ * @param {TimeTrackMultiColorData} data {@link TimeTrackMultiColorData}
191
+ * Check Class constructor
192
+ */
193
+ setData(data) {
194
+ console.log(data);
195
+ if (this.gl) {
196
+ this._ready = false;
197
+ this.setDataAsFloat32Array(data);
198
+ this._ready = true;
199
+ } else {
200
+ this._data = data;
201
+ this._ready = false;
202
+ }
203
+ }
204
+
205
+ /**
206
+ * @param {TimeTrackMultiColorData} data {@link TimeTrackMultiColorData}
207
+ * @param {number} totalSize | if not provided, it is calculated from float32Array.length / 9. Use if you want to draw first n points.
208
+ */
209
+ setDataAsFloat32Array(data, totalSize = null) {
210
+
211
+ const { gl, _attrBuffer } = this;
212
+ gl.bindBuffer(gl.ARRAY_BUFFER, _attrBuffer);
213
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
214
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
215
+
216
+
217
+ // this.program.setInBuffer(data);
218
+
219
+ // this.pointProgram.setData(data);
220
+ if (totalSize) {
221
+ this._totalSize = totalSize;
222
+ } else {
223
+ this._totalSize = data.length / 9;
224
+ }
225
+ this.program.setTotalLength(this._totalSize);
226
+ this.pointProgram?.setDrawCount(this._totalSize / 2);
227
+
228
+ this._ready = true;
229
+ }
230
+
231
+ // ------------------------------
232
+ // --- globe Methods ---
233
+ // ------------------------------
234
+
235
+ draw3D(projMatrix, modelviewMatrix, transPos) {
236
+ if (!this._ready) return;
237
+ const { _headTime, _tailTime, program, _transporArr, globe } = this;
238
+ this.pointProgram?.draw();
239
+
240
+ _transporArr.set([transPos.x, transPos.y, transPos.z], 0);
241
+ const geomType = globe.api_GetCurrentGeometry();
242
+ if (geomType === 0) {
243
+ program.draw(_headTime, _tailTime, projMatrix, modelviewMatrix, _transporArr);
244
+ } else if (geomType === 1) {
245
+ const { width, height } = globe.api_GetCurrentWorldWH();
246
+ program.draw(_headTime, _tailTime, projMatrix, modelviewMatrix, _transporArr,
247
+ [width, height]);
248
+ } else {
249
+ console.error("Unknown geometry type", geomType);
250
+ }
251
+ }
252
+
253
+ resize(width, height) {
254
+ const { program, globe } = this;
255
+ width = width || globe.api_ScrW();
256
+ height = height || globe.api_ScrH();
257
+ program.resize(width, height);
258
+ }
259
+
260
+
261
+ init(globe, gl) {
262
+ this.globe = globe;
263
+ this.gl = gl;
264
+ this._attrBuffer = gl.createBuffer();
265
+ this.program = new TrackGlowLineProgram(gl, this._attrBuffer, globe.api_ScrW(), globe.api_ScrH(), this._options);
266
+ if (this._pointOptions?.isOn) this.pointProgram = new PointProgram(gl, globe, this._attrBuffer);
267
+
268
+ // this.pointProgram.setAttrBuffer(_attrBuffer);
269
+ this.setGeometry();
270
+ if (this._data) {
271
+ this._ready = true;
272
+ this.setDataAsFloat32Array(this._data);
273
+
274
+ this._data = null;
275
+ }
276
+ this.resize();
277
+ }
278
+
279
+
280
+ free() {
281
+ const { gl, _attrBuffer } = this;
282
+ this.program.free();
283
+ gl.deleteBuffer(_attrBuffer);
284
+ }
285
+
286
+
287
+ setGeometry() {
288
+ const { globe, program } = this;
289
+ program.setIs3D(globe.api_GetCurrentGeometry() === 0);
290
+ }
291
+
292
+ // ----------------------------------
293
+ // --- implicit methods ---
294
+ // ----------------------------------
295
+
296
+
297
+ _latLongToPixelXY(latitude, longitude) {
298
+ return {
299
+ x: (longitude + 180) / 360,
300
+ y: (90 - latitude) / 180
301
+ };
302
+ }
303
+ }
304
+
305
+
306
+
307
+
@@ -0,0 +1,704 @@
1
+ /**
2
+ * Author: Toprak Nihat Deniz Ozturk
3
+ */
4
+
5
+ import { createProgram, defaultblendfunction, shaderfunctions } from "../util";
6
+
7
+ export default class TrackGlowLineProgram {
8
+ /**
9
+ * @param {WebGL2RenderingContext} gl
10
+ * @param {number} width
11
+ * @param {number} height
12
+ * @param {Object} options
13
+ * @param {number} options.headPercentage 0 ~ 1
14
+ * @param {number} options.routeAlpha 0 ~ 1
15
+ * @param {Array.<Number>} options.weights [w1, w2, w3, w4, w5]
16
+ * @param {number} options.alphaThreshold 0 ~ 1
17
+ * @param {number} options.exposure 0 ~ inf
18
+ * @param {number} options.gamma 0 ~ inf
19
+ * @param {number} options.finalAlphaRatio 0 ~ 1
20
+ * @param {+int} options.blurRepetition 1 ~ inf default 2
21
+ */
22
+ constructor(gl, attrBuffer, width, height, options = {}) {
23
+ this.gl = gl;
24
+ this.program = null;
25
+
26
+
27
+ // this._inBuffer = gl.createBuffer();
28
+ this._inBuffer = attrBuffer;
29
+
30
+ this._frameBuffer = gl.createFramebuffer();
31
+ this._lineProgram = this._createLineProgram();
32
+ this._blurProgram = this._createBlurProgram();
33
+ this._combineProgram = this._createCombineProgram();
34
+ this.resize(width, height);
35
+
36
+ this._middleTexture = null;
37
+ this._blurTextures = null;
38
+ this._createInnerTextures();
39
+
40
+ this._blurFrameBuffers = [gl.createFramebuffer(), gl.createFramebuffer()];
41
+
42
+ this._blurRepetition = options.blurRepetition || 1;
43
+ this._totalLength = 0;
44
+ this._initUniforms(options);
45
+ }
46
+
47
+
48
+ _createInnerTextures() {
49
+ this._middleTexture = this._createTextures();
50
+ this._blurTextures = [this._createTextures(), this._createTextures()];
51
+ }
52
+
53
+ _initUniforms(options = {}) {
54
+ const { gl, _lineProgram, _blurProgram, _combineProgram } = this;
55
+
56
+ const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
57
+
58
+ gl.useProgram(_lineProgram.program);
59
+ gl.uniform1f(_lineProgram.u_head_percentage, options.headPercentage || 1.0 / 30.0);
60
+ gl.uniform1f(_lineProgram.u_route_alpha, options.routeAlpha || 0.025);
61
+
62
+ gl.useProgram(_blurProgram.program);
63
+ gl.uniform1fv(_blurProgram.u_weight, options.weights || [1, 0.45045946, 0.2216216, 0.154054, 0.056216]);
64
+
65
+ gl.useProgram(_combineProgram.program);
66
+ gl.uniform1f(_combineProgram.u_exposure, options.exposure || 1.0);
67
+ gl.uniform1f(_combineProgram.u_gamma, options.gamma || 1.0);
68
+ gl.uniform1f(_combineProgram.u_final_alpha_ratio, options.finalAlphaRatio || 1.0);
69
+ gl.useProgram(currentProgram);
70
+ }
71
+
72
+
73
+
74
+ setPremultipliedAlpha(boolean) {
75
+ throw new Error("setPremultipliedAlpha method is depricated. Please remove it from your code.");
76
+ }
77
+
78
+
79
+ setAlphaThreshold(alpha) {
80
+ throw new Error("setAlphaThreshold method is depricated. Please remove it from your code.");
81
+ }
82
+
83
+
84
+ /**
85
+ * @param {number} gamma 0 ~ inf
86
+ */
87
+ setGamma(gamma) {
88
+ if (gamma < 0) {
89
+ console.warn("gamma should be equal or greater than 0, but got", gamma);
90
+ return;
91
+ }
92
+ const { gl, _combineProgram } = this;
93
+ const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
94
+ gl.useProgram(_combineProgram.program);
95
+ gl.uniform1f(_combineProgram.u_gamma, gamma);
96
+ gl.useProgram(currentProgram);
97
+ }
98
+
99
+ /**
100
+ *
101
+ * @param {number} exposure 0 ~ inf
102
+ * @returns
103
+ */
104
+ setExposure(exposure) {
105
+ if (exposure < 0) {
106
+ console.warn("exposure should be equal or greater than 0, but got", exposure);
107
+ return;
108
+ }
109
+ const { gl, _combineProgram } = this;
110
+ const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
111
+ gl.useProgram(_combineProgram.program);
112
+ gl.uniform1f(_combineProgram.u_exposure, exposure);
113
+ gl.useProgram(currentProgram);
114
+ }
115
+
116
+
117
+ /**
118
+ *
119
+ * @param {number} ratio 0 ~ 1
120
+ * @returns
121
+ */
122
+ setFinalAlphaRatio(ratio) {
123
+ if (ratio < 0 || ratio > 1) {
124
+ console.warn("ratio should be between 0 and 1, but got", ratio);
125
+ return;
126
+ }
127
+ const { gl, _combineProgram } = this;
128
+ const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
129
+ gl.useProgram(_combineProgram.program);
130
+ gl.uniform1f(_combineProgram.u_final_alpha_ratio, ratio);
131
+ gl.useProgram(currentProgram);
132
+
133
+ }
134
+
135
+ /**
136
+ * @param {Array.<Number>} weight [w1, w2, w3, w4, w5]
137
+ */
138
+ setBlurWeights(weights) {
139
+ if (weights.length !== 5) {
140
+ console.warn("weights should be an array of 5 numbers, but got", weights);
141
+ return;
142
+ }
143
+ const { gl, _blurProgram } = this;
144
+ const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
145
+ gl.useProgram(_blurProgram.program);
146
+ gl.uniform1fv(_blurProgram.u_weight, weights);
147
+ gl.useProgram(currentProgram);
148
+ }
149
+
150
+
151
+ /**
152
+ * @param {number} routeAlpha 0 ~ 1
153
+ */
154
+ setRouteAlpha(routeAlpha) {
155
+ if (routeAlpha < 0 || routeAlpha > 1) {
156
+ console.warn("routeAlpha should be between 0 and 1, but got", routeAlpha);
157
+ return;
158
+ }
159
+ const { gl, _lineProgram } = this;
160
+ const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
161
+ gl.useProgram(_lineProgram.program);
162
+ gl.uniform1f(_lineProgram.u_route_alpha, routeAlpha);
163
+ gl.useProgram(currentProgram);
164
+ }
165
+
166
+ setGlow(boolean) {
167
+ throw new Error("setGlow method is depricated. Please remove it from your code.");
168
+ }
169
+
170
+ /**
171
+ * blur uses pingpong effect. This number decides how many times the blur will be applied.
172
+ * @param {+int} repetition
173
+ * @returns
174
+ */
175
+ setBlurRepetition(repetition) {
176
+ if (repetition < 0 && repetition % 1 !== 0) {
177
+ console.warn("repetition should be an integer greater than 0, but got", repetition);
178
+ return;
179
+ }
180
+ this._blurRepetition = repetition;
181
+ }
182
+
183
+ /**
184
+ * Head Is colored as white. This number decides proportion of the head according to the total length of the line.
185
+ * @param {Number} percentage 0 ~ 1
186
+ */
187
+ setHeadPercentage(percentage) {
188
+ if (percentage < 0 || 1 < percentage) {
189
+ console.warn("percentage should be between 0 and 1, but got", percentage);
190
+ return
191
+ };
192
+ const { gl, _lineProgram } = this;
193
+ const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
194
+ gl.useProgram(_lineProgram.program);
195
+ gl.uniform1f(_lineProgram.u_head_percentage, percentage);
196
+ gl.useProgram(currentProgram);
197
+ }
198
+
199
+
200
+ _createDrawTextureProgram() {
201
+ const gl = this.gl;
202
+
203
+ const vertexShader = `#version 300 es
204
+ precision highp float;
205
+
206
+ in vec2 a_position;
207
+
208
+ out vec2 v_texcoord;
209
+
210
+ void main() {
211
+ gl_Position = vec4(a_position, 0.0, 1.0);
212
+ v_texcoord = a_position.xy * 0.5 + 0.5;
213
+ }
214
+ `;
215
+
216
+ const fragmentShader = `#version 300 es
217
+ precision highp float;
218
+
219
+ in vec2 v_texcoord;
220
+
221
+ uniform sampler2D u_main_texture;
222
+
223
+
224
+ uniform float u_final_alpha_ratio;
225
+
226
+ out vec4 outColor;
227
+
228
+ void main() {
229
+
230
+ vec4 hdrColor = texture(u_main_texture, v_texcoord);
231
+ outColor = hdrColor;
232
+ outColor.a *= u_final_alpha_ratio;
233
+ }
234
+ `;
235
+ const program = createProgram(this.gl, vertexShader, fragmentShader);
236
+
237
+ const buffer = gl.createBuffer();
238
+ const a_position = gl.getAttribLocation(program, "a_position");
239
+ const vao = gl.createVertexArray();
240
+ gl.bindVertexArray(vao);
241
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
242
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
243
+ -1, -1,
244
+ 1, -1,
245
+ 1, 1,
246
+ -1, -1,
247
+ 1, 1,
248
+ -1, 1,
249
+ ]), gl.STATIC_DRAW);
250
+ gl.enableVertexAttribArray(a_position);
251
+ gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0);
252
+ gl.bindVertexArray(null);
253
+
254
+ return {
255
+ program: program,
256
+ vao: vao,
257
+ u_main_texture: gl.getUniformLocation(program, "u_main_texture"),
258
+ u_final_alpha_ratio: gl.getUniformLocation(program, "u_final_alpha_ratio"),
259
+ };
260
+ }
261
+
262
+
263
+ _createCombineProgram() {
264
+ const gl = this.gl;
265
+
266
+ const vertexShader = `#version 300 es
267
+ precision highp float;
268
+
269
+ in vec2 a_position;
270
+
271
+ out vec2 v_texcoord;
272
+
273
+ void main() {
274
+ gl_Position = vec4(a_position, 0.0, 1.0);
275
+ v_texcoord = a_position.xy * 0.5 + 0.5;
276
+ }
277
+ `;
278
+
279
+ const fragmentShader = `#version 300 es
280
+ precision highp float;
281
+
282
+ in vec2 v_texcoord;
283
+
284
+ uniform sampler2D u_main_texture;
285
+ uniform sampler2D u_bloom_texture;
286
+
287
+ uniform float u_exposure;
288
+ uniform float u_gamma;
289
+ uniform float u_final_alpha_ratio;
290
+
291
+ out vec4 outColor;
292
+
293
+ void main() {
294
+
295
+ vec4 hdrColor = texture(u_main_texture, v_texcoord);
296
+ vec4 bloomColor = texture(u_bloom_texture, v_texcoord);
297
+ vec4 result = hdrColor + bloomColor * u_exposure;
298
+ result = pow(result, vec4(1.0 / u_gamma));
299
+ result.a *= u_final_alpha_ratio;
300
+ outColor = result;
301
+ }
302
+ `;
303
+ const program = createProgram(this.gl, vertexShader, fragmentShader);
304
+
305
+ const buffer = gl.createBuffer();
306
+ const a_position = gl.getAttribLocation(program, "a_position");
307
+ const vao = gl.createVertexArray();
308
+ gl.bindVertexArray(vao);
309
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
310
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
311
+ -1, -1,
312
+ 1, -1,
313
+ 1, 1,
314
+ -1, -1,
315
+ 1, 1,
316
+ -1, 1,
317
+ ]), gl.STATIC_DRAW);
318
+ gl.enableVertexAttribArray(a_position);
319
+ gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0);
320
+ gl.bindVertexArray(null);
321
+
322
+ return {
323
+ program: program,
324
+ vao: vao,
325
+ u_main_texture: gl.getUniformLocation(program, "u_main_texture"),
326
+ u_bloom_texture: gl.getUniformLocation(program, "u_bloom_texture"),
327
+ u_exposure: gl.getUniformLocation(program, "u_exposure"),
328
+ u_gamma: gl.getUniformLocation(program, "u_gamma"),
329
+ u_final_alpha_ratio: gl.getUniformLocation(program, "u_final_alpha_ratio"),
330
+ };
331
+ }
332
+
333
+
334
+ _createBlurProgram() {
335
+ const gl = this.gl;
336
+
337
+ const vertexShader = `#version 300 es
338
+ precision highp float;
339
+
340
+ in vec2 a_position;
341
+ out vec2 v_texcoord;
342
+
343
+ void main() {
344
+ gl_Position = vec4(a_position, 0.0, 1.0);
345
+ v_texcoord = a_position.xy * 0.5 + 0.5;
346
+ }`;
347
+ const fragmentShader = `#version 300 es
348
+ precision highp float;
349
+
350
+ in vec2 v_texcoord;
351
+
352
+ uniform sampler2D u_texture;
353
+ uniform bool u_horizontal;
354
+ uniform float u_weight[5];
355
+ out vec4 outColor;
356
+
357
+ void main()
358
+ {
359
+ vec2 tex_offset = vec2(
360
+ 1.0 / float(textureSize(u_texture, 0).x),
361
+ 1.0 / float(textureSize(u_texture, 0).y) ); // gets size of single texel
362
+ vec3 color = vec3(0.0);
363
+ float total_alpha = texture(u_texture, v_texcoord).a * u_weight[0];
364
+ if (total_alpha > 0.0){
365
+ color = texture(u_texture, v_texcoord).rgb;
366
+ }
367
+ vec2 offset = vec2(0.0);
368
+ float alpha;
369
+
370
+ if(u_horizontal){
371
+ for(int i = 1; i < 5; ++i){
372
+ offset = vec2(tex_offset.x * float(i), 0.0);
373
+ alpha = texture(u_texture, v_texcoord + offset).a * u_weight[i];
374
+ color = mix( color, texture(u_texture, v_texcoord + offset).rgb, alpha);
375
+ total_alpha += alpha;
376
+ alpha = texture(u_texture, v_texcoord - offset).a * u_weight[i];
377
+ color = mix( color, texture(u_texture, v_texcoord - offset).rgb, alpha);
378
+ total_alpha += alpha;
379
+ }
380
+ }
381
+ else
382
+ {
383
+ for(int i = 1; i < 5; ++i)
384
+ {
385
+ offset = vec2(0.0, tex_offset.y * float(i));
386
+ alpha = texture(u_texture, v_texcoord + offset).a * u_weight[i];
387
+ color = mix( color, texture(u_texture, v_texcoord + offset).rgb, alpha);
388
+ total_alpha += alpha;
389
+ alpha = texture(u_texture, v_texcoord - offset).a * u_weight[i];
390
+ color = mix( color, texture(u_texture, v_texcoord - offset).rgb, alpha);
391
+ total_alpha += alpha;
392
+ }
393
+ }
394
+ outColor = vec4(color, total_alpha);
395
+ }
396
+ `;
397
+
398
+ const program = createProgram(this.gl, vertexShader, fragmentShader);
399
+
400
+ const buffer = gl.createBuffer();
401
+ const a_position = gl.getAttribLocation(program, "a_position");
402
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
403
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
404
+ -1, -1,
405
+ 1, -1,
406
+ 1, 1,
407
+ -1, -1,
408
+ 1, 1,
409
+ -1, 1,
410
+ ]), gl.STATIC_DRAW);
411
+ const vao = gl.createVertexArray();
412
+ gl.bindVertexArray(vao);
413
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
414
+ gl.enableVertexAttribArray(a_position);
415
+
416
+ gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0);
417
+ gl.bindVertexArray(null);
418
+
419
+ return {
420
+ program: program,
421
+ vao: vao,
422
+ u_texture: gl.getUniformLocation(program, "u_texture"),
423
+ u_horizontal: gl.getUniformLocation(program, "u_horizontal"),
424
+ u_weight: gl.getUniformLocation(program, "u_weight"),
425
+ };
426
+ }
427
+
428
+
429
+ resize(width, height) {
430
+ const { gl, _lineProgram } = this;
431
+ this._width = width;
432
+ this._height = height;
433
+ const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
434
+ this._createInnerTextures();
435
+ gl.useProgram(_lineProgram.program);
436
+ gl.uniform2fv(_lineProgram.u_scrWH, [width, height]);
437
+ gl.useProgram(currentProgram);
438
+ }
439
+
440
+ _createLineProgram() {
441
+
442
+ const gl = this.gl;
443
+
444
+ const vertexShader = `#version 300 es
445
+ precision highp float;
446
+
447
+ in vec3 a_position;
448
+ in float a_time;
449
+ in vec3 a_color;
450
+ in float a_track_start_time;
451
+ in float a_track_end_time;
452
+
453
+ uniform mat4 uModelViewMatrix;
454
+ uniform mat4 uProjectionMatrix;
455
+ uniform vec3 uTranslate;
456
+
457
+ uniform bool u_is_3d;
458
+ uniform vec2 u_mapWH;
459
+ uniform vec2 u_scrWH;
460
+
461
+ out float v_time;
462
+ out vec3 v_color;
463
+ out float v_track_start_time;
464
+ out float v_track_end_time;
465
+ ${shaderfunctions.pixelXYToCartesian3DPoint}
466
+ ${shaderfunctions.pixelXYToCartesian2DPoint}
467
+
468
+ void main() {
469
+ if ( a_color.x < .0 || a_color.y < .0 || a_color.z < .0) {
470
+ v_time = -1000000000.0;
471
+ v_track_end_time = -1000000000.0;
472
+ v_track_start_time = -1000000001.0;
473
+ return;
474
+ }
475
+ v_time = a_time;
476
+ v_color = a_color;
477
+ v_track_start_time = a_track_start_time;
478
+ v_track_end_time = a_track_end_time;
479
+ if (u_is_3d){
480
+ vec3 pos = pixelXYToCartesian3DPoint(a_position);
481
+ gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(pos - uTranslate, 1.0);
482
+ } else {
483
+ vec2 xy = pixelXYToCartesian2DPoint(a_position.xy, uTranslate.xy, u_mapWH, u_scrWH);
484
+ gl_Position = uProjectionMatrix * vec4(xy.x, xy.y, 0.0, 1.0);
485
+ }
486
+ }
487
+ `;
488
+
489
+ const fragmentShader = `#version 300 es
490
+ precision lowp float;
491
+
492
+ in float v_time;
493
+ in vec3 v_color;
494
+ in float v_track_start_time;
495
+ in float v_track_end_time;
496
+ uniform float u_head_time;
497
+ uniform float u_tail_time;
498
+
499
+ uniform float u_head_percentage;
500
+ uniform float u_route_alpha;
501
+
502
+ layout(location = 0) out vec4 outColor0;
503
+ layout(location = 1) out vec4 outColor1;
504
+
505
+
506
+ void main() {
507
+ if ( u_tail_time > v_track_end_time || u_head_time < v_track_start_time) discard;
508
+ float gap = u_head_time - u_tail_time;
509
+ float head = gap * u_head_percentage;
510
+ float dist = u_head_time - v_time;
511
+
512
+ if ((v_time > u_head_time ) || (v_time < u_tail_time) ){
513
+ outColor0 = vec4(v_color , u_route_alpha);
514
+ return;
515
+ } else if (dist < head) {
516
+ // white head
517
+ outColor1 = vec4(1.0, 1.0, 1.0, 1.0);
518
+ //
519
+ } else {
520
+ // colored body of lines
521
+ float alpha = ((gap - dist) / gap) * 0.4 + 0.6;
522
+ // outColor0 = vec4(v_color , alpha );
523
+ outColor1 = vec4(v_color , alpha );
524
+ }
525
+ outColor0 = vec4(v_color , 1.0);
526
+ }
527
+ `;
528
+ const program = createProgram(this.gl, vertexShader, fragmentShader);
529
+ const a_position = gl.getAttribLocation(program, "a_position");
530
+ const a_time = gl.getAttribLocation(program, "a_time");
531
+ const a_track_start_time = gl.getAttribLocation(program, "a_track_start_time");
532
+ const a_track_end_time = gl.getAttribLocation(program, "a_track_end_time");
533
+ const a_color = gl.getAttribLocation(program, "a_color");
534
+
535
+ const vao = gl.createVertexArray();
536
+ gl.bindVertexArray(vao);
537
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._inBuffer);
538
+ gl.enableVertexAttribArray(a_position);
539
+ gl.vertexAttribPointer(a_position, 3, gl.FLOAT, false, 36, 0);
540
+ gl.enableVertexAttribArray(a_time);
541
+ gl.vertexAttribPointer(a_time, 1, gl.FLOAT, false, 36, 12);
542
+ gl.enableVertexAttribArray(a_color);
543
+ gl.vertexAttribPointer(a_color, 3, gl.FLOAT, false, 36, 16);
544
+ gl.enableVertexAttribArray(a_track_start_time);
545
+ gl.vertexAttribPointer(a_track_start_time, 1, gl.FLOAT, false, 36, 28);
546
+ gl.enableVertexAttribArray(a_track_end_time);
547
+ gl.vertexAttribPointer(a_track_end_time, 1, gl.FLOAT, false, 36, 32);
548
+ gl.bindVertexArray(null);
549
+ return {
550
+ program: program,
551
+ vao: vao,
552
+ u_head_time: gl.getUniformLocation(program, "u_head_time"),
553
+ u_tail_time: gl.getUniformLocation(program, "u_tail_time"),
554
+ uTranslate: gl.getUniformLocation(program, "uTranslate"),
555
+ uModelViewMatrix: gl.getUniformLocation(program, "uModelViewMatrix"),
556
+ uProjectionMatrix: gl.getUniformLocation(program, "uProjectionMatrix"),
557
+ u_is_3d: gl.getUniformLocation(program, "u_is_3d"),
558
+ u_mapWH: gl.getUniformLocation(program, "u_mapWH"),
559
+ u_scrWH: gl.getUniformLocation(program, "u_scrWH"),
560
+ u_head_percentage: gl.getUniformLocation(program, "u_head_percentage"),
561
+ u_route_alpha: gl.getUniformLocation(program, "u_route_alpha"),
562
+ };
563
+ }
564
+
565
+
566
+ /**
567
+ * @param { Float32Array} data // [x, y, z, time, x, y, z, time, ...]
568
+ */
569
+ // setInBuffer(data) {
570
+ // const gl = this.gl;
571
+ // gl.bindBuffer(gl.ARRAY_BUFFER, this._inBuffer);
572
+ // gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
573
+ // }
574
+
575
+
576
+
577
+ setIs3D(is3d) {
578
+ const { gl, _lineProgram } = this;
579
+ const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
580
+ gl.useProgram(_lineProgram.program);
581
+ gl.uniform1i(_lineProgram.u_is_3d, is3d);
582
+ gl.useProgram(currentProgram);
583
+ }
584
+
585
+
586
+ setTotalLength(totalLength) {
587
+ this._totalLength = totalLength;
588
+ }
589
+
590
+
591
+ _createTextures() {
592
+ const { gl, _width, _height } = this;
593
+
594
+ const texture = gl.createTexture();
595
+ gl.bindTexture(gl.TEXTURE_2D, texture);
596
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, _width, _height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); // UNSIGNED_BYTE
597
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
598
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
599
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
600
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
601
+ gl.bindTexture(gl.TEXTURE_2D, null);
602
+ return texture;
603
+ }
604
+
605
+ _resetTexture() {
606
+ const { gl, _width, _height } = this;
607
+ gl.bindTexture(gl.TEXTURE_2D, this._middleTexture); // UNSIGNED_BYTE
608
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, _width, _height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
609
+ gl.bindTexture(gl.TEXTURE_2D, this._blurTextures[0]);
610
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, _width, _height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
611
+ gl.bindTexture(gl.TEXTURE_2D, this._blurTextures[1]);
612
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, _width, _height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
613
+ gl.bindTexture(gl.TEXTURE_2D, null);
614
+ }
615
+
616
+
617
+
618
+ draw(u_head_time, u_tail_time, uProjectionMatrix, uModelViewMatrix, uTranslate, u_mapWH = null) {
619
+ const { gl, _lineProgram, _blurProgram, _blurRepetition } = this;
620
+ this._resetTexture();
621
+
622
+ gl.enable(gl.BLEND);
623
+ gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
624
+
625
+ { // draw lines
626
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
627
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._middleTexture, 0);
628
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, this._blurTextures[0], 0);
629
+ gl.drawBuffers([
630
+ gl.COLOR_ATTACHMENT0,
631
+ gl.COLOR_ATTACHMENT1,
632
+
633
+ ])
634
+ gl.useProgram(_lineProgram.program);
635
+ gl.uniform1f(_lineProgram.u_head_time, u_head_time);
636
+ gl.uniform1f(_lineProgram.u_tail_time, u_tail_time);
637
+ gl.uniformMatrix4fv(_lineProgram.uProjectionMatrix, false, uProjectionMatrix);
638
+ if (u_mapWH) {
639
+ gl.uniform2fv(_lineProgram.u_mapWH, u_mapWH);
640
+
641
+ } else {
642
+ gl.uniformMatrix4fv(_lineProgram.uModelViewMatrix, false, uModelViewMatrix);
643
+ }
644
+ gl.uniform3fv(_lineProgram.uTranslate, uTranslate);
645
+
646
+ gl.bindVertexArray(_lineProgram.vao);
647
+ gl.drawArrays(gl.LINE_STRIP, 0, this._totalLength); // TODO: line_strip with thombstone to reduce buffer size in half
648
+ gl.drawBuffers([
649
+ gl.COLOR_ATTACHMENT0,
650
+ gl.NONE
651
+ ])
652
+ }
653
+
654
+ { // blur ping pong
655
+ gl.useProgram(_blurProgram.program);
656
+ gl.bindVertexArray(_blurProgram.vao);
657
+ for (let i = 0; i < _blurRepetition * 2; i++) {
658
+ gl.bindFramebuffer(gl.FRAMEBUFFER, this._blurFrameBuffers[i % 2]);
659
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._blurTextures[(i + 1) % 2], 0);
660
+ gl.bindTexture(gl.TEXTURE_2D, this._blurTextures[i % 2]);
661
+ gl.uniform1i(_blurProgram.u_texture, 0);
662
+ gl.uniform1f(_blurProgram.u_horizontal, i % 2 == 0);
663
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
664
+ }
665
+ }
666
+
667
+ { // combine
668
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
669
+ gl.useProgram(this._combineProgram.program);
670
+ gl.bindVertexArray(this._combineProgram.vao);
671
+ gl.activeTexture(gl.TEXTURE1);
672
+ gl.bindTexture(gl.TEXTURE_2D, this._blurTextures[1]);
673
+ gl.uniform1i(this._combineProgram.u_bloom_texture, 1);
674
+ gl.activeTexture(gl.TEXTURE0);
675
+ gl.bindTexture(gl.TEXTURE_2D, this._middleTexture);
676
+ gl.uniform1i(this._combineProgram.u_main_texture, 0);
677
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
678
+ }
679
+ gl.bindVertexArray(null);
680
+
681
+ defaultblendfunction(gl)
682
+
683
+ }
684
+
685
+
686
+ free() {
687
+ const { gl, _lineProgram, _blurProgram, _combineProgram } = this;
688
+ gl.deleteBuffer(this._inBuffer);
689
+ gl.deleteFramebuffer(this._frameBuffer);
690
+ gl.deleteFramebuffer(this._blurFrameBuffers[0]);
691
+ gl.deleteFramebuffer(this._blurFrameBuffers[1]);
692
+ // gl.deleteBuffer(this._middleTexture);
693
+ gl.deleteTexture(this._middleTexture);
694
+ gl.deleteTexture(this._blurTextures[0]);
695
+ gl.deleteTexture(this._blurTextures[1]);
696
+ gl.deleteVertexArray(_lineProgram.vao);
697
+ gl.deleteVertexArray(_blurProgram.vao);
698
+ gl.deleteVertexArray(_combineProgram.vao);
699
+ gl.deleteProgram(_lineProgram.program);
700
+ gl.deleteProgram(_blurProgram.program);
701
+ gl.deleteProgram(_combineProgram.program);
702
+ }
703
+ }
704
+
@@ -0,0 +1,175 @@
1
+ import { createProgram, shaderfunctions } from "../util";
2
+ import { CameraUniformBlockTotem, globeProgramCache } from "../programs";
3
+
4
+
5
+ const vertexShader = `#version 300 es
6
+
7
+ layout(std140) uniform GlobeCamera {
8
+ mat4 view; // 64 bytes 0
9
+ mat4 projection; // 64 bytes 64
10
+ vec3 translate; // 12 bytes 128
11
+ bool is3D; // 4 bytes 140
12
+ vec2 mapWH; // 8 bytes 144
13
+ vec2 screenWH; // 8 bytes 152
14
+ float z_level; // 4 bytes 160
15
+ };
16
+
17
+ layout(std140) uniform Globals {
18
+ float head_time;
19
+ float final_opacity;
20
+ float point_size;
21
+ };
22
+
23
+ in vec3 start_position;
24
+ in float start_time;
25
+ in vec3 start_color;
26
+ in vec3 end_position;
27
+ in float end_time;
28
+ in vec3 end_color;
29
+ out vec4 v_color;
30
+
31
+ `+ shaderfunctions.pixelXYToCartesian3DPoint + shaderfunctions.pixelXYToCartesian2DPoint + `
32
+
33
+ void main() {
34
+ if (head_time < start_time || head_time > end_time) { return; }
35
+ if ( start_color.r < 0.0 || end_color.r < 0.0) { return; }
36
+ float t = (head_time - start_time) / (end_time - start_time);
37
+ vec3 position = mix(start_position, end_position, t);
38
+ if (is3D){
39
+ vec3 pos = pixelXYToCartesian3DPoint(position);
40
+ gl_Position = projection * view * vec4(pos - translate, 1.0);
41
+ } else {
42
+ vec2 xy = pixelXYToCartesian2DPoint(position.xy, translate.xy, mapWH, screenWH);
43
+ gl_Position = projection * vec4(xy.x, xy.y, 0.0, 1.0);
44
+ }
45
+ v_color = vec4(mix(start_color, end_color, t), final_opacity);
46
+ gl_PointSize = point_size;
47
+ }`;
48
+
49
+ const fragmentShader = `#version 300 es
50
+ precision highp float;
51
+ in vec4 v_color;
52
+ out vec4 outColor;
53
+ void main() {
54
+ // circle point
55
+ vec2 cxy = 2.0 * gl_PointCoord - 1.0;
56
+ float cc = dot(cxy, cxy);
57
+ outColor = v_color;
58
+ if (cc > 0.5) {
59
+ outColor.a = 0.0;
60
+ }
61
+ }`;
62
+
63
+
64
+ export default class {
65
+
66
+ constructor(gl, globe, attrBuffer, options) {
67
+
68
+ this.gl = gl;
69
+ this._cameraBlockBindingPoint = 0;
70
+ this._globalsBlockBindingPoint = 1;
71
+ this.cameraUniformBlockTotem = globeProgramCache.getProgram(globe, CameraUniformBlockTotem);
72
+ this._vao = gl.createVertexArray();
73
+ this._attbuffer = attrBuffer;
74
+ this.program = this._createProgram();
75
+ this._drawCount = 0;
76
+
77
+ this._globalsbuffer = gl.createBuffer();
78
+ {
79
+ const { gl, _globalsbuffer } = this;
80
+ gl.bindBuffer(gl.UNIFORM_BUFFER, _globalsbuffer);
81
+ gl.bufferData(gl.UNIFORM_BUFFER, 12, gl.STREAM_DRAW); // TODO: sperate head time to make it dynamic maybe?
82
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array([0, options.opacity, options.pointSize]));
83
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, this._globalsBlockBindingPoint, _globalsbuffer);
84
+ gl.bindBuffer(gl.UNIFORM_BUFFER, null);
85
+ }
86
+ }
87
+
88
+
89
+ _createProgram() {
90
+ const gl = this.gl
91
+
92
+ const program = createProgram(gl, vertexShader, fragmentShader);
93
+ const ubo = this.cameraUniformBlockTotem.getUBO(); // ubo bl
94
+ const cameraBlockIndex = gl.getUniformBlockIndex(program, "GlobeCamera");
95
+ gl.uniformBlockBinding(program, cameraBlockIndex, this._cameraBlockBindingPoint);
96
+ const globalsBlockIndex = gl.getUniformBlockIndex(program, "Globals");
97
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, this._cameraBlockBindingPoint, ubo);
98
+ gl.uniformBlockBinding(program, globalsBlockIndex, this._globalsBlockBindingPoint);
99
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, this._globalsBlockBindingPoint, this._globalsbuffer);
100
+
101
+ // numaralarda yanlışlık olabilir
102
+ const start_position = gl.getAttribLocation(program, "start_position");
103
+ const start_time = gl.getAttribLocation(program, "start_time");
104
+ const start_color = gl.getAttribLocation(program, "start_color");
105
+ const end_position = gl.getAttribLocation(program, "end_position");
106
+ const end_time = gl.getAttribLocation(program, "end_time");
107
+ const end_color = gl.getAttribLocation(program, "end_color");
108
+
109
+ gl.bindVertexArray(this._vao);
110
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._attbuffer);
111
+ gl.enableVertexAttribArray(start_position);
112
+ gl.vertexAttribPointer(start_position, 3, gl.FLOAT, false, 36, 0);
113
+ gl.enableVertexAttribArray(start_time);
114
+ gl.vertexAttribPointer(start_time, 1, gl.FLOAT, false, 36, 12);
115
+ gl.enableVertexAttribArray(start_color);
116
+ gl.vertexAttribPointer(start_color, 3, gl.FLOAT, false, 36, 16);
117
+ gl.enableVertexAttribArray(end_position);
118
+ gl.vertexAttribPointer(end_position, 3, gl.FLOAT, false, 36, 36);
119
+ gl.enableVertexAttribArray(end_time);
120
+ gl.vertexAttribPointer(end_time, 1, gl.FLOAT, false, 36, 48);
121
+ gl.enableVertexAttribArray(end_color);
122
+ gl.vertexAttribPointer(end_color, 3, gl.FLOAT, false, 36, 52);
123
+ gl.bindVertexArray(null);
124
+ gl.bindBuffer(gl.ARRAY_BUFFER, null);
125
+ return program;
126
+ }
127
+
128
+
129
+ setOpacity(opacity) {
130
+ const { gl, _globalsbuffer } = this;
131
+ gl.bindBuffer(gl.UNIFORM_BUFFER, _globalsbuffer);
132
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 4, new Float32Array([opacity]));
133
+ gl.bindBuffer(gl.UNIFORM_BUFFER, null);
134
+ }
135
+
136
+ setDrawCount(count) {
137
+ this._drawCount = count;
138
+ }
139
+
140
+
141
+ setPointSize(size) {
142
+ const { gl, _globalsbuffer } = this;
143
+ gl.bindBuffer(gl.UNIFORM_BUFFER, _globalsbuffer);
144
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 8, new Float32Array([size]));
145
+ gl.bindBuffer(gl.UNIFORM_BUFFER, null);
146
+ }
147
+
148
+
149
+ setHeadTime(time) {
150
+ const { gl, _globalsbuffer } = this;
151
+ gl.bindBuffer(gl.UNIFORM_BUFFER, _globalsbuffer);
152
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array([time]));
153
+ gl.bindBuffer(gl.UNIFORM_BUFFER, null);
154
+ }
155
+
156
+
157
+ draw() {
158
+ const { gl, program, _vao, _drawCount } = this;
159
+ gl.useProgram(program);
160
+ gl.bindVertexArray(_vao);
161
+ gl.disable(gl.DEPTH_TEST);
162
+ gl.drawArrays(gl.POINTS, 0, _drawCount);
163
+ gl.enable(gl.DEPTH_TEST);
164
+ gl.bindVertexArray(null);
165
+ }
166
+
167
+
168
+ free() {
169
+ const { gl, _vao, _globalsbuffer, program } = this;
170
+ gl.deleteVertexArray(_vao);
171
+ // gl.deleteBuffer(_attbuffer);
172
+ gl.deleteBuffer(_globalsbuffer);
173
+ gl.deleteProgram(program);
174
+ }
175
+ }