@pirireis/webglobeplugins 0.6.32-a → 0.6.35
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/bearing-line/plugin.js +1 -1
- package/circle-line-chain/plugin.js +1 -0
- package/package.json +1 -1
- package/timetracks/adaptors-line-strip.js +80 -0
- package/timetracks/index.js +4 -1
- package/timetracks/plugin-line-strip.js +294 -0
- package/timetracks/program-line-strip.js +693 -0
- package/timetracks/programpoint-line-strip.js +175 -0
package/bearing-line/plugin.js
CHANGED
package/package.json
CHANGED
|
@@ -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 };
|
package/timetracks/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import TimeTracks from './plugin';
|
|
2
2
|
import { Adaptor, fillSliceOfFloat32Array, createFloat32Array } from './adaptors';
|
|
3
|
-
|
|
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,294 @@
|
|
|
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
|
+
setBlurWeights(weights) {
|
|
93
|
+
this.program.setBlurWeights(weights);
|
|
94
|
+
this.globe.DrawRender();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
setHeadPercentage(headPercentage) {
|
|
98
|
+
this.program.setHeadPercentage(headPercentage);
|
|
99
|
+
this.globe.DrawRender();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
setRouteAlpha(routeAlpha) {
|
|
103
|
+
this.program.setRouteAlpha(routeAlpha);
|
|
104
|
+
this.globe.DrawRender();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
setFinalAlphaRatio(finalAlphaRatio) {
|
|
108
|
+
this.program.setFinalAlphaRatio(finalAlphaRatio);
|
|
109
|
+
this.globe.DrawRender();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
setGamma(gamma) {
|
|
113
|
+
this.program.setGamma(gamma);
|
|
114
|
+
this.globe.DrawRender();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
setExposure(exposure) {
|
|
118
|
+
this.program.setExposure(exposure);
|
|
119
|
+
this.globe.DrawRender();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
setBlurRepetition(repetition) {
|
|
123
|
+
this.program.setBlurRepetition(repetition);
|
|
124
|
+
this.globe.DrawRender();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
// ---------------point program setters-------------------
|
|
130
|
+
|
|
131
|
+
setPointOpacity(opacity) {
|
|
132
|
+
this._pointOptions.opacity = opacity;
|
|
133
|
+
if (this.pointProgram) {
|
|
134
|
+
this.pointProgram.setOpacity(opacity);
|
|
135
|
+
this.globe.DrawRender();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
setPointSize(size) {
|
|
140
|
+
this._pointOptions.pointSize = size;
|
|
141
|
+
if (this.pointProgram) {
|
|
142
|
+
this.pointProgram.setPointSize(size);
|
|
143
|
+
this.globe.DrawRender();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
pointSwitch(isOn) {
|
|
148
|
+
if (isOn && !this.pointProgram) {
|
|
149
|
+
this.pointProgram = this._createPointProgram();
|
|
150
|
+
} else {
|
|
151
|
+
this._deletePointProgram();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ------------------------------------------------------------
|
|
157
|
+
|
|
158
|
+
_createPointProgram() {
|
|
159
|
+
const { gl } = this;
|
|
160
|
+
const program = new PointProgram(gl, this.globe, this._attrBuffer, this._pointOptions);
|
|
161
|
+
program.setDrawCount(this._totalSize);
|
|
162
|
+
return program;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
_deletePointProgram() {
|
|
166
|
+
if (this.pointProgram) this.pointProgram.free();
|
|
167
|
+
this.pointProgram = null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// -------------------------------------------------------------
|
|
171
|
+
|
|
172
|
+
isReady() {
|
|
173
|
+
return this._ready;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @param {TimeTrackMultiColorData} data {@link TimeTrackMultiColorData}
|
|
178
|
+
* Check Class constructor
|
|
179
|
+
*/
|
|
180
|
+
setData(data) {
|
|
181
|
+
console.log(data);
|
|
182
|
+
if (this.gl) {
|
|
183
|
+
this._ready = false;
|
|
184
|
+
this.setDataAsFloat32Array(data);
|
|
185
|
+
this._ready = true;
|
|
186
|
+
} else {
|
|
187
|
+
this._data = data;
|
|
188
|
+
this._ready = false;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* @param {TimeTrackMultiColorData} data {@link TimeTrackMultiColorData}
|
|
194
|
+
* @param {number} totalSize | if not provided, it is calculated from float32Array.length / 9. Use if you want to draw first n points.
|
|
195
|
+
*/
|
|
196
|
+
setDataAsFloat32Array(data, totalSize = null) {
|
|
197
|
+
|
|
198
|
+
const { gl, _attrBuffer } = this;
|
|
199
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, _attrBuffer);
|
|
200
|
+
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
|
|
201
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
// this.program.setInBuffer(data);
|
|
205
|
+
|
|
206
|
+
// this.pointProgram.setData(data);
|
|
207
|
+
if (totalSize) {
|
|
208
|
+
this._totalSize = totalSize;
|
|
209
|
+
} else {
|
|
210
|
+
this._totalSize = data.length / 9;
|
|
211
|
+
}
|
|
212
|
+
this.program.setTotalLength(this._totalSize);
|
|
213
|
+
this.pointProgram?.setDrawCount(this._totalSize / 2);
|
|
214
|
+
|
|
215
|
+
this._ready = true;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ------------------------------
|
|
219
|
+
// --- globe Methods ---
|
|
220
|
+
// ------------------------------
|
|
221
|
+
|
|
222
|
+
draw3D(projMatrix, modelviewMatrix, transPos) {
|
|
223
|
+
if (!this._ready) return;
|
|
224
|
+
const { _headTime, _tailTime, program, _transporArr, globe } = this;
|
|
225
|
+
this.pointProgram?.draw();
|
|
226
|
+
|
|
227
|
+
_transporArr.set([transPos.x, transPos.y, transPos.z], 0);
|
|
228
|
+
const geomType = globe.api_GetCurrentGeometry();
|
|
229
|
+
if (geomType === 0) {
|
|
230
|
+
program.draw(_headTime, _tailTime, projMatrix, modelviewMatrix, _transporArr);
|
|
231
|
+
} else if (geomType === 1) {
|
|
232
|
+
const { width, height } = globe.api_GetCurrentWorldWH();
|
|
233
|
+
program.draw(_headTime, _tailTime, projMatrix, modelviewMatrix, _transporArr,
|
|
234
|
+
[width, height]);
|
|
235
|
+
} else {
|
|
236
|
+
console.error("Unknown geometry type", geomType);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
resize(width, height) {
|
|
241
|
+
const { program, globe } = this;
|
|
242
|
+
width = width || globe.api_ScrW();
|
|
243
|
+
height = height || globe.api_ScrH();
|
|
244
|
+
program.resize(width, height);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
init(globe, gl) {
|
|
249
|
+
this.globe = globe;
|
|
250
|
+
this.gl = gl;
|
|
251
|
+
this._attrBuffer = gl.createBuffer();
|
|
252
|
+
this.program = new TrackGlowLineProgram(gl, this._attrBuffer, globe.api_ScrW(), globe.api_ScrH(), this._options);
|
|
253
|
+
if (this._pointOptions?.isOn) this.pointProgram = new PointProgram(gl, globe, this._attrBuffer);
|
|
254
|
+
|
|
255
|
+
// this.pointProgram.setAttrBuffer(_attrBuffer);
|
|
256
|
+
this.setGeometry();
|
|
257
|
+
if (this._data) {
|
|
258
|
+
this._ready = true;
|
|
259
|
+
this.setDataAsFloat32Array(this._data);
|
|
260
|
+
|
|
261
|
+
this._data = null;
|
|
262
|
+
}
|
|
263
|
+
this.resize();
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
free() {
|
|
268
|
+
const { gl, _attrBuffer } = this;
|
|
269
|
+
this.program.free();
|
|
270
|
+
gl.deleteBuffer(_attrBuffer);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
setGeometry() {
|
|
275
|
+
const { globe, program } = this;
|
|
276
|
+
program.setIs3D(globe.api_GetCurrentGeometry() === 0);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// ----------------------------------
|
|
280
|
+
// --- implicit methods ---
|
|
281
|
+
// ----------------------------------
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
_latLongToPixelXY(latitude, longitude) {
|
|
285
|
+
return {
|
|
286
|
+
x: (longitude + 180) / 360,
|
|
287
|
+
y: (90 - latitude) / 180
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
|
|
@@ -0,0 +1,693 @@
|
|
|
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 || [0.55, 0.45045946, 0.3216216, 0.254054, 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
|
+
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @param {number} gamma 0 ~ inf
|
|
78
|
+
*/
|
|
79
|
+
setGamma(gamma) {
|
|
80
|
+
if (gamma < 0) {
|
|
81
|
+
console.warn("gamma should be equal or greater than 0, but got", gamma);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const { gl, _combineProgram } = this;
|
|
85
|
+
const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
|
|
86
|
+
gl.useProgram(_combineProgram.program);
|
|
87
|
+
gl.uniform1f(_combineProgram.u_gamma, gamma);
|
|
88
|
+
gl.useProgram(currentProgram);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
*
|
|
93
|
+
* @param {number} exposure 0 ~ inf
|
|
94
|
+
* @returns
|
|
95
|
+
*/
|
|
96
|
+
setExposure(exposure) {
|
|
97
|
+
if (exposure < 0) {
|
|
98
|
+
console.warn("exposure should be equal or greater than 0, but got", exposure);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const { gl, _combineProgram } = this;
|
|
102
|
+
const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
|
|
103
|
+
gl.useProgram(_combineProgram.program);
|
|
104
|
+
gl.uniform1f(_combineProgram.u_exposure, exposure);
|
|
105
|
+
gl.useProgram(currentProgram);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
*
|
|
111
|
+
* @param {number} ratio 0 ~ 1
|
|
112
|
+
* @returns
|
|
113
|
+
*/
|
|
114
|
+
setFinalAlphaRatio(ratio) {
|
|
115
|
+
if (ratio < 0 || ratio > 1) {
|
|
116
|
+
console.warn("ratio should be between 0 and 1, but got", ratio);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const { gl, _combineProgram } = this;
|
|
120
|
+
const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
|
|
121
|
+
gl.useProgram(_combineProgram.program);
|
|
122
|
+
gl.uniform1f(_combineProgram.u_final_alpha_ratio, ratio);
|
|
123
|
+
gl.useProgram(currentProgram);
|
|
124
|
+
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @param {Array.<Number>} weight [w1, w2, w3, w4, w5]
|
|
129
|
+
*/
|
|
130
|
+
setBlurWeights(weights) {
|
|
131
|
+
if (weights.length !== 5) {
|
|
132
|
+
console.warn("weights should be an array of 5 numbers, but got", weights);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const { gl, _blurProgram } = this;
|
|
136
|
+
const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
|
|
137
|
+
gl.useProgram(_blurProgram.program);
|
|
138
|
+
gl.uniform1fv(_blurProgram.u_weight, weights);
|
|
139
|
+
gl.useProgram(currentProgram);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* @param {number} routeAlpha 0 ~ 1
|
|
145
|
+
*/
|
|
146
|
+
setRouteAlpha(routeAlpha) {
|
|
147
|
+
if (routeAlpha < 0 || routeAlpha > 1) {
|
|
148
|
+
console.warn("routeAlpha should be between 0 and 1, but got", routeAlpha);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const { gl, _lineProgram } = this;
|
|
152
|
+
const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
|
|
153
|
+
gl.useProgram(_lineProgram.program);
|
|
154
|
+
gl.uniform1f(_lineProgram.u_route_alpha, routeAlpha);
|
|
155
|
+
gl.useProgram(currentProgram);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* blur uses pingpong effect. This number decides how many times the blur will be applied.
|
|
161
|
+
* @param {+int} repetition
|
|
162
|
+
* @returns
|
|
163
|
+
*/
|
|
164
|
+
setBlurRepetition(repetition) {
|
|
165
|
+
if (repetition < 0 && repetition % 1 !== 0) {
|
|
166
|
+
console.warn("repetition should be an integer greater than 0, but got", repetition);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
this._blurRepetition = repetition;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Head Is colored as white. This number decides proportion of the head according to the total length of the line.
|
|
174
|
+
* @param {Number} percentage 0 ~ 1
|
|
175
|
+
*/
|
|
176
|
+
setHeadPercentage(percentage) {
|
|
177
|
+
if (percentage < 0 || 1 < percentage) {
|
|
178
|
+
console.warn("percentage should be between 0 and 1, but got", percentage);
|
|
179
|
+
return
|
|
180
|
+
};
|
|
181
|
+
const { gl, _lineProgram } = this;
|
|
182
|
+
const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
|
|
183
|
+
gl.useProgram(_lineProgram.program);
|
|
184
|
+
gl.uniform1f(_lineProgram.u_head_percentage, percentage);
|
|
185
|
+
gl.useProgram(currentProgram);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
_createDrawTextureProgram() {
|
|
190
|
+
const gl = this.gl;
|
|
191
|
+
|
|
192
|
+
const vertexShader = `#version 300 es
|
|
193
|
+
precision highp float;
|
|
194
|
+
|
|
195
|
+
in vec2 a_position;
|
|
196
|
+
|
|
197
|
+
out vec2 v_texcoord;
|
|
198
|
+
|
|
199
|
+
void main() {
|
|
200
|
+
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
201
|
+
v_texcoord = a_position.xy * 0.5 + 0.5;
|
|
202
|
+
}
|
|
203
|
+
`;
|
|
204
|
+
|
|
205
|
+
const fragmentShader = `#version 300 es
|
|
206
|
+
precision highp float;
|
|
207
|
+
|
|
208
|
+
in vec2 v_texcoord;
|
|
209
|
+
|
|
210
|
+
uniform sampler2D u_main_texture;
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
uniform float u_final_alpha_ratio;
|
|
214
|
+
|
|
215
|
+
out vec4 outColor;
|
|
216
|
+
|
|
217
|
+
void main() {
|
|
218
|
+
|
|
219
|
+
vec4 hdrColor = texture(u_main_texture, v_texcoord);
|
|
220
|
+
outColor = hdrColor;
|
|
221
|
+
outColor.a *= u_final_alpha_ratio;
|
|
222
|
+
}
|
|
223
|
+
`;
|
|
224
|
+
const program = createProgram(this.gl, vertexShader, fragmentShader);
|
|
225
|
+
|
|
226
|
+
const buffer = gl.createBuffer();
|
|
227
|
+
const a_position = gl.getAttribLocation(program, "a_position");
|
|
228
|
+
const vao = gl.createVertexArray();
|
|
229
|
+
gl.bindVertexArray(vao);
|
|
230
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
231
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
|
|
232
|
+
-1, -1,
|
|
233
|
+
1, -1,
|
|
234
|
+
1, 1,
|
|
235
|
+
-1, -1,
|
|
236
|
+
1, 1,
|
|
237
|
+
-1, 1,
|
|
238
|
+
]), gl.STATIC_DRAW);
|
|
239
|
+
gl.enableVertexAttribArray(a_position);
|
|
240
|
+
gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0);
|
|
241
|
+
gl.bindVertexArray(null);
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
program: program,
|
|
245
|
+
vao: vao,
|
|
246
|
+
u_main_texture: gl.getUniformLocation(program, "u_main_texture"),
|
|
247
|
+
u_final_alpha_ratio: gl.getUniformLocation(program, "u_final_alpha_ratio"),
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
_createCombineProgram() {
|
|
253
|
+
const gl = this.gl;
|
|
254
|
+
|
|
255
|
+
const vertexShader = `#version 300 es
|
|
256
|
+
precision highp float;
|
|
257
|
+
|
|
258
|
+
in vec2 a_position;
|
|
259
|
+
|
|
260
|
+
out vec2 v_texcoord;
|
|
261
|
+
|
|
262
|
+
void main() {
|
|
263
|
+
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
264
|
+
v_texcoord = a_position.xy * 0.5 + 0.5;
|
|
265
|
+
}
|
|
266
|
+
`;
|
|
267
|
+
|
|
268
|
+
const fragmentShader = `#version 300 es
|
|
269
|
+
precision highp float;
|
|
270
|
+
|
|
271
|
+
in vec2 v_texcoord;
|
|
272
|
+
|
|
273
|
+
uniform sampler2D u_main_texture;
|
|
274
|
+
uniform sampler2D u_bloom_texture;
|
|
275
|
+
|
|
276
|
+
uniform float u_exposure;
|
|
277
|
+
uniform float u_gamma;
|
|
278
|
+
uniform float u_final_alpha_ratio;
|
|
279
|
+
|
|
280
|
+
out vec4 outColor;
|
|
281
|
+
|
|
282
|
+
void main() {
|
|
283
|
+
|
|
284
|
+
vec4 hdrColor = texture(u_main_texture, v_texcoord);
|
|
285
|
+
vec4 bloomColor = texture(u_bloom_texture, v_texcoord);
|
|
286
|
+
vec4 result = hdrColor + bloomColor * u_exposure;
|
|
287
|
+
result = pow(result, vec4(1.0 / u_gamma));
|
|
288
|
+
result.a *= u_final_alpha_ratio;
|
|
289
|
+
outColor = result;
|
|
290
|
+
}
|
|
291
|
+
`;
|
|
292
|
+
const program = createProgram(this.gl, vertexShader, fragmentShader);
|
|
293
|
+
|
|
294
|
+
const buffer = gl.createBuffer();
|
|
295
|
+
const a_position = gl.getAttribLocation(program, "a_position");
|
|
296
|
+
const vao = gl.createVertexArray();
|
|
297
|
+
gl.bindVertexArray(vao);
|
|
298
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
299
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
|
|
300
|
+
-1, -1,
|
|
301
|
+
1, -1,
|
|
302
|
+
1, 1,
|
|
303
|
+
-1, -1,
|
|
304
|
+
1, 1,
|
|
305
|
+
-1, 1,
|
|
306
|
+
]), gl.STATIC_DRAW);
|
|
307
|
+
gl.enableVertexAttribArray(a_position);
|
|
308
|
+
gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0);
|
|
309
|
+
gl.bindVertexArray(null);
|
|
310
|
+
|
|
311
|
+
return {
|
|
312
|
+
program: program,
|
|
313
|
+
vao: vao,
|
|
314
|
+
u_main_texture: gl.getUniformLocation(program, "u_main_texture"),
|
|
315
|
+
u_bloom_texture: gl.getUniformLocation(program, "u_bloom_texture"),
|
|
316
|
+
u_exposure: gl.getUniformLocation(program, "u_exposure"),
|
|
317
|
+
u_gamma: gl.getUniformLocation(program, "u_gamma"),
|
|
318
|
+
u_final_alpha_ratio: gl.getUniformLocation(program, "u_final_alpha_ratio"),
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
_createBlurProgram() {
|
|
324
|
+
const gl = this.gl;
|
|
325
|
+
|
|
326
|
+
const vertexShader = `#version 300 es
|
|
327
|
+
precision highp float;
|
|
328
|
+
|
|
329
|
+
in vec2 a_position;
|
|
330
|
+
out vec2 v_texcoord;
|
|
331
|
+
|
|
332
|
+
void main() {
|
|
333
|
+
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
334
|
+
v_texcoord = a_position.xy * 0.5 + 0.5;
|
|
335
|
+
}`;
|
|
336
|
+
const fragmentShader = `#version 300 es
|
|
337
|
+
precision highp float;
|
|
338
|
+
|
|
339
|
+
in vec2 v_texcoord;
|
|
340
|
+
|
|
341
|
+
uniform sampler2D u_texture;
|
|
342
|
+
uniform bool u_horizontal;
|
|
343
|
+
uniform float u_weight[5];
|
|
344
|
+
out vec4 outColor;
|
|
345
|
+
|
|
346
|
+
void main()
|
|
347
|
+
{
|
|
348
|
+
vec2 tex_offset = vec2(
|
|
349
|
+
1.0 / float(textureSize(u_texture, 0).x),
|
|
350
|
+
1.0 / float(textureSize(u_texture, 0).y) ); // gets size of single texel
|
|
351
|
+
vec3 color = vec3(0.0);
|
|
352
|
+
float total_alpha = texture(u_texture, v_texcoord).a * u_weight[0];
|
|
353
|
+
if (total_alpha > 0.0){
|
|
354
|
+
color = texture(u_texture, v_texcoord).rgb;
|
|
355
|
+
}
|
|
356
|
+
vec2 offset = vec2(0.0);
|
|
357
|
+
float alpha;
|
|
358
|
+
|
|
359
|
+
if(u_horizontal){
|
|
360
|
+
for(int i = 1; i < 5; ++i){
|
|
361
|
+
offset = vec2(tex_offset.x * float(i), 0.0);
|
|
362
|
+
alpha = texture(u_texture, v_texcoord + offset).a * u_weight[i];
|
|
363
|
+
color = mix( color, texture(u_texture, v_texcoord + offset).rgb, alpha);
|
|
364
|
+
total_alpha += alpha;
|
|
365
|
+
alpha = texture(u_texture, v_texcoord - offset).a * u_weight[i];
|
|
366
|
+
color = mix( color, texture(u_texture, v_texcoord - offset).rgb, alpha);
|
|
367
|
+
total_alpha += alpha;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
else
|
|
371
|
+
{
|
|
372
|
+
for(int i = 1; i < 5; ++i)
|
|
373
|
+
{
|
|
374
|
+
offset = vec2(0.0, tex_offset.y * float(i));
|
|
375
|
+
alpha = texture(u_texture, v_texcoord + offset).a * u_weight[i];
|
|
376
|
+
color = mix( color, texture(u_texture, v_texcoord + offset).rgb, alpha);
|
|
377
|
+
total_alpha += alpha;
|
|
378
|
+
alpha = texture(u_texture, v_texcoord - offset).a * u_weight[i];
|
|
379
|
+
color = mix( color, texture(u_texture, v_texcoord - offset).rgb, alpha);
|
|
380
|
+
total_alpha += alpha;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
outColor = vec4(color, total_alpha);
|
|
384
|
+
}
|
|
385
|
+
`;
|
|
386
|
+
|
|
387
|
+
const program = createProgram(this.gl, vertexShader, fragmentShader);
|
|
388
|
+
|
|
389
|
+
const buffer = gl.createBuffer();
|
|
390
|
+
const a_position = gl.getAttribLocation(program, "a_position");
|
|
391
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
392
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
|
|
393
|
+
-1, -1,
|
|
394
|
+
1, -1,
|
|
395
|
+
1, 1,
|
|
396
|
+
-1, -1,
|
|
397
|
+
1, 1,
|
|
398
|
+
-1, 1,
|
|
399
|
+
]), gl.STATIC_DRAW);
|
|
400
|
+
const vao = gl.createVertexArray();
|
|
401
|
+
gl.bindVertexArray(vao);
|
|
402
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
403
|
+
gl.enableVertexAttribArray(a_position);
|
|
404
|
+
|
|
405
|
+
gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0);
|
|
406
|
+
gl.bindVertexArray(null);
|
|
407
|
+
|
|
408
|
+
return {
|
|
409
|
+
program: program,
|
|
410
|
+
vao: vao,
|
|
411
|
+
u_texture: gl.getUniformLocation(program, "u_texture"),
|
|
412
|
+
u_horizontal: gl.getUniformLocation(program, "u_horizontal"),
|
|
413
|
+
u_weight: gl.getUniformLocation(program, "u_weight"),
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
resize(width, height) {
|
|
419
|
+
const { gl, _lineProgram } = this;
|
|
420
|
+
this._width = width;
|
|
421
|
+
this._height = height;
|
|
422
|
+
const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
|
|
423
|
+
this._createInnerTextures();
|
|
424
|
+
gl.useProgram(_lineProgram.program);
|
|
425
|
+
gl.uniform2fv(_lineProgram.u_scrWH, [width, height]);
|
|
426
|
+
gl.useProgram(currentProgram);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
_createLineProgram() {
|
|
430
|
+
|
|
431
|
+
const gl = this.gl;
|
|
432
|
+
|
|
433
|
+
const vertexShader = `#version 300 es
|
|
434
|
+
precision highp float;
|
|
435
|
+
|
|
436
|
+
in vec3 a_position;
|
|
437
|
+
in float a_time;
|
|
438
|
+
in vec3 a_color;
|
|
439
|
+
in float a_track_start_time;
|
|
440
|
+
in float a_track_end_time;
|
|
441
|
+
|
|
442
|
+
uniform mat4 uModelViewMatrix;
|
|
443
|
+
uniform mat4 uProjectionMatrix;
|
|
444
|
+
uniform vec3 uTranslate;
|
|
445
|
+
|
|
446
|
+
uniform bool u_is_3d;
|
|
447
|
+
uniform vec2 u_mapWH;
|
|
448
|
+
uniform vec2 u_scrWH;
|
|
449
|
+
|
|
450
|
+
out float v_time;
|
|
451
|
+
out vec3 v_color;
|
|
452
|
+
out float v_track_start_time;
|
|
453
|
+
out float v_track_end_time;
|
|
454
|
+
${shaderfunctions.pixelXYToCartesian3DPoint}
|
|
455
|
+
${shaderfunctions.pixelXYToCartesian2DPoint}
|
|
456
|
+
|
|
457
|
+
void main() {
|
|
458
|
+
if ( a_color.x < .0 || a_color.y < .0 || a_color.z < .0) {
|
|
459
|
+
v_time = -1000000000.0;
|
|
460
|
+
v_track_end_time = -1000000000.0;
|
|
461
|
+
v_track_start_time = -1000000001.0;
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
v_time = a_time;
|
|
465
|
+
v_color = a_color;
|
|
466
|
+
v_track_start_time = a_track_start_time;
|
|
467
|
+
v_track_end_time = a_track_end_time;
|
|
468
|
+
if (u_is_3d){
|
|
469
|
+
vec3 pos = pixelXYToCartesian3DPoint(a_position);
|
|
470
|
+
gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(pos - uTranslate, 1.0);
|
|
471
|
+
} else {
|
|
472
|
+
vec2 xy = pixelXYToCartesian2DPoint(a_position.xy, uTranslate.xy, u_mapWH, u_scrWH);
|
|
473
|
+
gl_Position = uProjectionMatrix * vec4(xy.x, xy.y, 0.0, 1.0);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
`;
|
|
477
|
+
|
|
478
|
+
const fragmentShader = `#version 300 es
|
|
479
|
+
precision lowp float;
|
|
480
|
+
|
|
481
|
+
in float v_time;
|
|
482
|
+
in vec3 v_color;
|
|
483
|
+
in float v_track_start_time;
|
|
484
|
+
in float v_track_end_time;
|
|
485
|
+
uniform float u_head_time;
|
|
486
|
+
uniform float u_tail_time;
|
|
487
|
+
|
|
488
|
+
uniform float u_head_percentage;
|
|
489
|
+
uniform float u_route_alpha;
|
|
490
|
+
|
|
491
|
+
layout(location = 0) out vec4 outColor0;
|
|
492
|
+
layout(location = 1) out vec4 outColor1;
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
void main() {
|
|
496
|
+
if ( u_tail_time > v_track_end_time || u_head_time < v_track_start_time) discard;
|
|
497
|
+
float gap = u_head_time - u_tail_time;
|
|
498
|
+
float head = gap * u_head_percentage;
|
|
499
|
+
float dist = u_head_time - v_time;
|
|
500
|
+
|
|
501
|
+
if ((v_time > u_head_time ) || (v_time < u_tail_time) ){
|
|
502
|
+
outColor0 = vec4(v_color , u_route_alpha);
|
|
503
|
+
return;
|
|
504
|
+
} else if (dist < head) {
|
|
505
|
+
// white head
|
|
506
|
+
outColor1 = vec4(1.0, 1.0, 1.0, 1.0);
|
|
507
|
+
//
|
|
508
|
+
} else {
|
|
509
|
+
// colored body of lines
|
|
510
|
+
float alpha = ((gap - dist) / gap) * 0.4 + 0.6;
|
|
511
|
+
// outColor0 = vec4(v_color , alpha );
|
|
512
|
+
outColor1 = vec4(v_color , alpha );
|
|
513
|
+
}
|
|
514
|
+
outColor0 = vec4(v_color , 1.0);
|
|
515
|
+
}
|
|
516
|
+
`;
|
|
517
|
+
const program = createProgram(this.gl, vertexShader, fragmentShader);
|
|
518
|
+
const a_position = gl.getAttribLocation(program, "a_position");
|
|
519
|
+
const a_time = gl.getAttribLocation(program, "a_time");
|
|
520
|
+
const a_track_start_time = gl.getAttribLocation(program, "a_track_start_time");
|
|
521
|
+
const a_track_end_time = gl.getAttribLocation(program, "a_track_end_time");
|
|
522
|
+
const a_color = gl.getAttribLocation(program, "a_color");
|
|
523
|
+
|
|
524
|
+
const vao = gl.createVertexArray();
|
|
525
|
+
gl.bindVertexArray(vao);
|
|
526
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this._inBuffer);
|
|
527
|
+
gl.enableVertexAttribArray(a_position);
|
|
528
|
+
gl.vertexAttribPointer(a_position, 3, gl.FLOAT, false, 36, 0);
|
|
529
|
+
gl.enableVertexAttribArray(a_time);
|
|
530
|
+
gl.vertexAttribPointer(a_time, 1, gl.FLOAT, false, 36, 12);
|
|
531
|
+
gl.enableVertexAttribArray(a_color);
|
|
532
|
+
gl.vertexAttribPointer(a_color, 3, gl.FLOAT, false, 36, 16);
|
|
533
|
+
gl.enableVertexAttribArray(a_track_start_time);
|
|
534
|
+
gl.vertexAttribPointer(a_track_start_time, 1, gl.FLOAT, false, 36, 28);
|
|
535
|
+
gl.enableVertexAttribArray(a_track_end_time);
|
|
536
|
+
gl.vertexAttribPointer(a_track_end_time, 1, gl.FLOAT, false, 36, 32);
|
|
537
|
+
gl.bindVertexArray(null);
|
|
538
|
+
return {
|
|
539
|
+
program: program,
|
|
540
|
+
vao: vao,
|
|
541
|
+
u_head_time: gl.getUniformLocation(program, "u_head_time"),
|
|
542
|
+
u_tail_time: gl.getUniformLocation(program, "u_tail_time"),
|
|
543
|
+
uTranslate: gl.getUniformLocation(program, "uTranslate"),
|
|
544
|
+
uModelViewMatrix: gl.getUniformLocation(program, "uModelViewMatrix"),
|
|
545
|
+
uProjectionMatrix: gl.getUniformLocation(program, "uProjectionMatrix"),
|
|
546
|
+
u_is_3d: gl.getUniformLocation(program, "u_is_3d"),
|
|
547
|
+
u_mapWH: gl.getUniformLocation(program, "u_mapWH"),
|
|
548
|
+
u_scrWH: gl.getUniformLocation(program, "u_scrWH"),
|
|
549
|
+
u_head_percentage: gl.getUniformLocation(program, "u_head_percentage"),
|
|
550
|
+
u_route_alpha: gl.getUniformLocation(program, "u_route_alpha"),
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* @param { Float32Array} data // [x, y, z, time, x, y, z, time, ...]
|
|
557
|
+
*/
|
|
558
|
+
// setInBuffer(data) {
|
|
559
|
+
// const gl = this.gl;
|
|
560
|
+
// gl.bindBuffer(gl.ARRAY_BUFFER, this._inBuffer);
|
|
561
|
+
// gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
|
|
562
|
+
// }
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
setIs3D(is3d) {
|
|
567
|
+
const { gl, _lineProgram } = this;
|
|
568
|
+
const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
|
|
569
|
+
gl.useProgram(_lineProgram.program);
|
|
570
|
+
gl.uniform1i(_lineProgram.u_is_3d, is3d);
|
|
571
|
+
gl.useProgram(currentProgram);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
setTotalLength(totalLength) {
|
|
576
|
+
this._totalLength = totalLength;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
_createTextures() {
|
|
581
|
+
const { gl, _width, _height } = this;
|
|
582
|
+
|
|
583
|
+
const texture = gl.createTexture();
|
|
584
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
585
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, _width, _height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); // UNSIGNED_BYTE
|
|
586
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
587
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
588
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
589
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
590
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
591
|
+
return texture;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
_resetTexture() {
|
|
595
|
+
const { gl, _width, _height } = this;
|
|
596
|
+
gl.bindTexture(gl.TEXTURE_2D, this._middleTexture); // UNSIGNED_BYTE
|
|
597
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, _width, _height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
|
598
|
+
gl.bindTexture(gl.TEXTURE_2D, this._blurTextures[0]);
|
|
599
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, _width, _height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
|
600
|
+
gl.bindTexture(gl.TEXTURE_2D, this._blurTextures[1]);
|
|
601
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, _width, _height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
|
602
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
draw(u_head_time, u_tail_time, uProjectionMatrix, uModelViewMatrix, uTranslate, u_mapWH = null) {
|
|
608
|
+
const { gl, _lineProgram, _blurProgram, _blurRepetition } = this;
|
|
609
|
+
this._resetTexture();
|
|
610
|
+
|
|
611
|
+
gl.enable(gl.BLEND);
|
|
612
|
+
gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
613
|
+
|
|
614
|
+
{ // draw lines
|
|
615
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this._frameBuffer);
|
|
616
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._middleTexture, 0);
|
|
617
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, this._blurTextures[0], 0);
|
|
618
|
+
gl.drawBuffers([
|
|
619
|
+
gl.COLOR_ATTACHMENT0,
|
|
620
|
+
gl.COLOR_ATTACHMENT1,
|
|
621
|
+
|
|
622
|
+
])
|
|
623
|
+
gl.useProgram(_lineProgram.program);
|
|
624
|
+
gl.uniform1f(_lineProgram.u_head_time, u_head_time);
|
|
625
|
+
gl.uniform1f(_lineProgram.u_tail_time, u_tail_time);
|
|
626
|
+
gl.uniformMatrix4fv(_lineProgram.uProjectionMatrix, false, uProjectionMatrix);
|
|
627
|
+
if (u_mapWH) {
|
|
628
|
+
gl.uniform2fv(_lineProgram.u_mapWH, u_mapWH);
|
|
629
|
+
|
|
630
|
+
} else {
|
|
631
|
+
gl.uniformMatrix4fv(_lineProgram.uModelViewMatrix, false, uModelViewMatrix);
|
|
632
|
+
}
|
|
633
|
+
gl.uniform3fv(_lineProgram.uTranslate, uTranslate);
|
|
634
|
+
|
|
635
|
+
gl.bindVertexArray(_lineProgram.vao);
|
|
636
|
+
gl.drawArrays(gl.LINE_STRIP, 0, this._totalLength); // TODO: line_strip with thombstone to reduce buffer size in half
|
|
637
|
+
gl.drawBuffers([
|
|
638
|
+
gl.COLOR_ATTACHMENT0,
|
|
639
|
+
gl.NONE
|
|
640
|
+
])
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
{ // blur ping pong
|
|
644
|
+
gl.useProgram(_blurProgram.program);
|
|
645
|
+
gl.bindVertexArray(_blurProgram.vao);
|
|
646
|
+
for (let i = 0; i < _blurRepetition * 2; i++) {
|
|
647
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this._blurFrameBuffers[i % 2]);
|
|
648
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._blurTextures[(i + 1) % 2], 0);
|
|
649
|
+
gl.bindTexture(gl.TEXTURE_2D, this._blurTextures[i % 2]);
|
|
650
|
+
gl.uniform1i(_blurProgram.u_texture, 0);
|
|
651
|
+
gl.uniform1f(_blurProgram.u_horizontal, i % 2 == 0);
|
|
652
|
+
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
{ // combine
|
|
657
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
658
|
+
gl.useProgram(this._combineProgram.program);
|
|
659
|
+
gl.bindVertexArray(this._combineProgram.vao);
|
|
660
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
661
|
+
gl.bindTexture(gl.TEXTURE_2D, this._blurTextures[1]);
|
|
662
|
+
gl.uniform1i(this._combineProgram.u_bloom_texture, 1);
|
|
663
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
664
|
+
gl.bindTexture(gl.TEXTURE_2D, this._middleTexture);
|
|
665
|
+
gl.uniform1i(this._combineProgram.u_main_texture, 0);
|
|
666
|
+
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
667
|
+
}
|
|
668
|
+
gl.bindVertexArray(null);
|
|
669
|
+
|
|
670
|
+
defaultblendfunction(gl)
|
|
671
|
+
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
free() {
|
|
676
|
+
const { gl, _lineProgram, _blurProgram, _combineProgram } = this;
|
|
677
|
+
gl.deleteBuffer(this._inBuffer);
|
|
678
|
+
gl.deleteFramebuffer(this._frameBuffer);
|
|
679
|
+
gl.deleteFramebuffer(this._blurFrameBuffers[0]);
|
|
680
|
+
gl.deleteFramebuffer(this._blurFrameBuffers[1]);
|
|
681
|
+
// gl.deleteBuffer(this._middleTexture);
|
|
682
|
+
gl.deleteTexture(this._middleTexture);
|
|
683
|
+
gl.deleteTexture(this._blurTextures[0]);
|
|
684
|
+
gl.deleteTexture(this._blurTextures[1]);
|
|
685
|
+
gl.deleteVertexArray(_lineProgram.vao);
|
|
686
|
+
gl.deleteVertexArray(_blurProgram.vao);
|
|
687
|
+
gl.deleteVertexArray(_combineProgram.vao);
|
|
688
|
+
gl.deleteProgram(_lineProgram.program);
|
|
689
|
+
gl.deleteProgram(_blurProgram.program);
|
|
690
|
+
gl.deleteProgram(_combineProgram.program);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
|
|
@@ -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
|
+
}
|