@pirireis/webglobeplugins 0.6.30-c → 0.6.32-a

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.
@@ -41,18 +41,18 @@ export class CircleLineChainPlugin {
41
41
  /**
42
42
  *
43
43
  * @param {*} id
44
- * @param {Map<[key, ContextTextWriter3]} textContextWriterInjectionMap //import { ContextTextWriter3 } from "@pirireis/webglobeplugins/write-text/context-text3";
44
+ * @param {Map<[key, ContextTextWriter3]} textWritersMap //import { ContextTextWriter3 } from "@pirireis/webglobeplugins/write-text/context-text3";
45
45
  */
46
46
  constructor(id, {
47
47
  drawCircleOn = true,
48
- textContextWriterInjectionMap = new Map(),
48
+ textWritersMap = new Map(),
49
49
  textDataPreAdaptor = null,
50
50
  circleFlatEdgeCount = flatCircleEdgeCount - 2
51
51
  } = {}) {
52
52
  this.id = id;
53
- this._checkTextContextWriterInjectionMap(textContextWriterInjectionMap);
54
- this._textContextWriterInjectionMap = textContextWriterInjectionMap;
55
- this._textContextWriterInjectionMap.forEach((writer) => writer.setKeyAdaptor((v, i, c, properties) => v.__identity__));
53
+ this._checktextWritersMap(textWritersMap);
54
+ this._textWritersMap = textWritersMap;
55
+ this._textWritersMap.forEach((writer) => writer.setKeyAdaptor((v, i, c, properties) => v.__identity__));
56
56
  this._opacity = 1;
57
57
  this._chainListMap = new ChainListMap(keyMethod);
58
58
  this.bufferOrchestrator = new BufferOrchestrator({ capacity: 10 });
@@ -63,136 +63,15 @@ export class CircleLineChainPlugin {
63
63
 
64
64
  // init
65
65
 
66
- init(globe, gl) {
67
- this.gl = gl;
68
- this.globe = globe
69
- this._initOrchestrations()
70
- }
71
-
72
- _checkTextContextWriterInjectionMap(textContextWriterInjectionMap) {
73
- if (!(textContextWriterInjectionMap instanceof Map)) throw new Error("textContextWriterInjectionMap is not an instance of Map");
74
- textContextWriterInjectionMap.forEach((v) => {
75
- if (!(v instanceof ContextTextWriter3)) throw new Error("textContextWriterInjectionMap element is not an instance of ContextTextWriter3");
76
- });
77
- }
78
-
79
- _initOrchestrations() {
80
- const { gl, globe } = this;
81
- this.lineProgram = LineOnGlobeCache.get(globe);
82
- this.circleProgram2d = CircleCache.get(globe);
83
- this.circle3DProgram = Circle3DCache.get(globe);
84
-
85
- // this.lineToTheOriginProgram = LineToTheOriginCache.get(globe);
86
- const _circleFlatEdgeCount = this._circleFlatEdgeCount;
87
- {
88
- // createBuffers
89
- const bufferType = "DYNAMIC_DRAW";
90
- const initialCapacity = this.bufferOrchestrator.capacity;
91
- this.bufferManagersCompMap = new Map(
92
- [
93
- ["centerCoords2d", {
94
- 'bufferManager': new BufferManager(gl, 2, { bufferType, initialCapacity }),
95
- 'adaptor': (item) => new Float32Array(globe.api_GetMercator2DPoint(item.long, item.lat)),
96
- }],
97
- ["centerCoords3d", {
98
- 'bufferManager': new BufferManager(gl, 3, { bufferType, initialCapacity }),
99
- 'adaptor': (item) => new Float32Array(globe.api_GetCartesian3DPoint(item.long, item.lat, 0, 0)),
100
- }],
101
- ["targetCoords2d", {
102
- 'bufferManager': new BufferManager(gl, 2, { bufferType, initialCapacity }),
103
- 'adaptor': (item) => new Float32Array(globe.api_GetMercator2DPoint(item.targetLong, item.targetLat)),
104
- }],
105
- ["targetCoords3d", {
106
- 'bufferManager': new BufferManager(gl, 3, { bufferType, initialCapacity }),
107
- 'adaptor': (item) => new Float32Array(globe.api_GetCartesian3DPoint(item.targetLong, item.targetLat, 0, 0)),
108
- }],
109
- ["rgba", {
110
- 'bufferManager': new BufferManager(gl, 4, { bufferType, initialCapacity }),
111
- 'adaptor': (item) => {
112
- if (item.lineProperties?.rgba) return new Float32Array(item.lineProperties.rgba);
113
- return new Float32Array(item.chainProperties.rgba);
114
- }
115
- }],
116
- ["bigRadius", {
117
- 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
118
- 'adaptor': (item) => new Float32Array([item.bigRadius])
119
- }],
120
- ["dashRatio", {
121
- 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
122
- 'adaptor': (item) => new Float32Array([item.chainProperties.dashRatio])
123
- }],
124
-
125
- ["dashOpacity", {
126
- 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
127
- 'adaptor': (item) => new Float32Array([item.chainProperties.dashOpacity])
128
- }],
129
- ["circleDashAngle", {
130
- 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
131
- 'adaptor': (item) => {
132
- if (item.circleProperties?.circleDashAngle) return new Float32Array([item.circleProperties.circleDashAngle / 360]);
133
- return new Float32Array([item.chainProperties.circleDashAngle / 360]);
134
- }
135
- }],
136
- ["rgbaCircle", {
137
- "bufferManager": new BufferManager(gl, 4, { bufferType, initialCapacity }),
138
- "adaptor": (item) => {
139
- if (item.circleProperties?.rgba) return new Float32Array(item.circleProperties.rgba);
140
- return new Float32Array(item.chainProperties.rgba);
141
- }
142
- }],
143
- // Mercator buffers
144
- ["circleDashAngleMercator", {
145
- 'bufferManager': new BufferManager(gl, 1 * _circleFlatEdgeCount, { bufferType, initialCapacity }),
146
- 'adaptor': (item) => {
147
- if (item.circleProperties?.circleDashAngle) return new Float32Array([item.circleProperties.circleDashAngle / 360]);
148
- return populateFloat32Array.fillFloat32Array(_circleFlatEdgeCount, item.chainProperties.circleDashAngle / 360);
149
- }
150
- }],
151
- ["rgbaCircleMercator", { // 62
152
- "bufferManager": new BufferManager(gl, 4 * _circleFlatEdgeCount, { bufferType, initialCapacity }),
153
- "adaptor": (item) => {
154
- if (item.circleProperties?.rgba) return populateFloat32Array.fillWithListData(_circleFlatEdgeCount, item.circleProperties.rgba);
155
- return populateFloat32Array.fillWithListData(_circleFlatEdgeCount, item.chainProperties.rgba);
156
- }
157
- }],
158
- ["dashOpacityMercator", {
159
- 'bufferManager': new BufferManager(gl, 1 * _circleFlatEdgeCount, { bufferType, initialCapacity }),
160
- 'adaptor': (item) => populateFloat32Array.fillFloat32Array(_circleFlatEdgeCount, item.chainProperties.dashOpacity)
161
- }],
162
- ["centerCoords2dMercator", {
163
- 'bufferManager': new BufferManager(gl, 2 * _circleFlatEdgeCount, { bufferType, initialCapacity }),
164
- 'adaptor': (item) => item.centerCoords2dflat,
165
- }],
166
- ]
167
- );
168
- // (startPotisionBufferObj, endPositionBufferObj, dashRatioBufferObj, colorBufferObj)
169
- const obj = function (bufferManagerComp) {
170
- return { 'buffer': bufferManagerComp.bufferManager.buffer, 'stride': 0, 'offset': 0 }
171
- };
172
- this.lineVao = this.lineProgram.createVAO(
173
- ...['centerCoords2d', 'centerCoords3d', 'targetCoords2d', 'targetCoords3d', 'dashRatio', 'dashOpacity', 'rgba'].map(key => obj(this.bufferManagersCompMap.get(key))));
174
- this.circleVao2d = this.circleProgram2d.createVAO(
175
- ...["centerCoords2dMercator", "rgbaCircleMercator", "circleDashAngleMercator", "dashOpacityMercator"].map(key => obj(this.bufferManagersCompMap.get(key))));
176
- // this.toOriginVao = this.lineToTheOriginProgram.createVAO(
177
- // ...["targetCoords3d", "rgba"].map(key => obj(this.bufferManagersCompMap.get(key))));
178
- this.circle3DVao = this.circle3DProgram.createVAO(
179
- ...["centerCoords3d", "bigRadius", "rgbaCircle", "circleDashAngle", "dashOpacity"].map(key => obj(this.bufferManagersCompMap.get(key)))
180
- );
181
-
182
- }
183
-
184
- }
185
-
186
-
187
66
  // API
188
67
  setDrawCircleOn(bool) {
189
68
  if (typeof bool !== 'boolean') throw new Error("setDrawCircleOn parameter must be a boolean");
190
69
  this._drawCircleOn = bool;
191
70
  this.globe.DrawRender();
192
71
  }
193
- // -- update bulk family
72
+
73
+ // ---- updateBulk
194
74
  /**
195
- *
196
75
  * @param {Array<chain>} data
197
76
  * @typedef chain
198
77
  * @property {string} chainKey
@@ -220,7 +99,6 @@ export class CircleLineChainPlugin {
220
99
 
221
100
 
222
101
  /**
223
- *
224
102
  * @param {*} chainKey
225
103
  * @param {Array<{nodeKey, circleProperties:Map[propertyName ,value], lineProperties:Map[propertyName ,value] }} propertyMap
226
104
  */
@@ -232,7 +110,6 @@ export class CircleLineChainPlugin {
232
110
  }
233
111
 
234
112
  /**
235
- *
236
113
  * @param {*} chainKey
237
114
  * @param {Map<propertyName ,value} propertyMap
238
115
  */
@@ -242,7 +119,22 @@ export class CircleLineChainPlugin {
242
119
  if (textWriterIDs) this._updateTexts([chainKey], textWriterIDs);
243
120
  }
244
121
 
245
- // ---- insertBulk family
122
+
123
+ updateNodeCoordinates(node, chainKey, { textWriterIDs = [] } = {}) {
124
+ this._chainListMap.updateCoordsinatesOfNode(node, chainKey);
125
+ if (textWriterIDs) this._updateTexts([chainKey], textWriterIDs);
126
+ this._reconstructChains([chainKey]);
127
+ this.globe.DrawRender();
128
+ }
129
+
130
+
131
+ updateText(textWriterIDs) {
132
+ const chainKeyIterator = this._chainListMap.getAllChainKeysIterator();
133
+ this._updateTexts(chainKeyIterator, textWriterIDs);
134
+ }
135
+
136
+
137
+ // ---- insertBulk
246
138
  /**
247
139
  *
248
140
  * @param {Array<chain>} data
@@ -258,7 +150,7 @@ export class CircleLineChainPlugin {
258
150
  * @property {number} lat
259
151
  * @property {StyleProperties} circleProperties
260
152
  */
261
- insertBulk(data, { textWriterIDs = [] } = []) {
153
+ insertBulk(data, { textWriterIDs = [] } = {}) {
262
154
  // first insert everything to implicit structure,
263
155
  // then iterate over data again to update text
264
156
  // let _reconstractChainBufferData method interact with data and bufferOrchestrator.
@@ -275,7 +167,6 @@ export class CircleLineChainPlugin {
275
167
  }
276
168
 
277
169
  /**
278
- *
279
170
  * @param {{key, long, lat}} node
280
171
  * @param {*} chainKey
281
172
  * @param {*} theNodeKeyFront | node key of the next node, null places to the last
@@ -289,20 +180,10 @@ export class CircleLineChainPlugin {
289
180
  }
290
181
 
291
182
 
292
-
293
- updateNodeCoordinates(node, chainKey, { textWriterIDs = [] } = {}) {
294
- this._chainListMap.updateCoordsinatesOfNode(node, chainKey);
295
- if (textWriterIDs) this._updateTexts([chainKey], textWriterIDs);
296
- this._reconstructChains([chainKey]);
297
- this.globe.DrawRender();
298
- }
299
-
300
-
301
-
302
183
  setOpacity(opacity) {
303
184
  if (typeof opacity !== 'number') throw new Error("opacity must be a number");
304
185
  if (opacity < 0 || 1 < opacity) throw new Error("opacity must be between 0-1");
305
- this._textContextWriterInjectionMap.forEach((writer) => writer.setOpacity(opacity));
186
+ this._textWritersMap.forEach((writer) => writer.setOpacity(opacity));
306
187
  this._opacity = opacity;
307
188
  this.globe.DrawRender();
308
189
  }
@@ -322,8 +203,8 @@ export class CircleLineChainPlugin {
322
203
  for (const chainKey of chainKeys) {
323
204
  bufferKeys.push(...this._chainListMap.deleteChainAndReturnChainKeys(chainKey));
324
205
  }
325
- this._textContextWriterInjectionMap.forEach((writer) => writer.deleteTextBulk(bufferKeys));
326
- this._updateTexts(chainKeys, this._textContextWriterInjectionMap.keys());
206
+ this._textWritersMap.forEach((writer) => writer.deleteTextBulk(bufferKeys));
207
+ this._updateTexts(chainKeys, this._textWritersMap.keys());
327
208
  this.bufferOrchestrator.deleteBulk(bufferKeys, this.bufferManagersCompMap);
328
209
  this.globe.DrawRender();
329
210
  }
@@ -340,7 +221,7 @@ export class CircleLineChainPlugin {
340
221
  bufferKeys.push(...this._chainListMap.deleteNodesBelongToAChain(chainKey, nodeKeys));
341
222
  chainKeysToReconstuct.push(chainKey);
342
223
  });
343
- this._textContextWriterInjectionMap.forEach((writer) => writer.deleteTextBulk(bufferKeys));
224
+ this._textWritersMap.forEach((writer) => writer.deleteTextBulk(bufferKeys));
344
225
  this.bufferOrchestrator.deleteBulk(bufferKeys, this.bufferManagersCompMap);
345
226
  this._reconstructChains(chainKeysToReconstuct);
346
227
  this._updateTexts(chainKeysToReconstuct, textWriterIDs);
@@ -349,17 +230,129 @@ export class CircleLineChainPlugin {
349
230
  }
350
231
 
351
232
 
352
- updateText(textWriterIDs) {
353
- const chainKeyIterator = this._chainListMap.getAllChainKeysIterator();
354
- this._updateTexts(chainKeyIterator, textWriterIDs);
233
+ init(globe, gl) {
234
+ this.gl = gl;
235
+ this.globe = globe
236
+ this._initOrchestrations()
355
237
  }
356
238
 
357
-
358
239
  // implicit
359
240
 
241
+ _checktextWritersMap(textWritersMap) {
242
+ if (!(textWritersMap instanceof Map)) throw new Error("textWritersMap is not an instance of Map");
243
+ textWritersMap.forEach((v) => {
244
+ if (!(v instanceof ContextTextWriter3)) throw new Error("textWritersMap element is not an instance of ContextTextWriter3");
245
+ });
246
+ }
247
+
248
+ _initOrchestrations() {
249
+ const { gl, globe } = this;
250
+ this.lineProgram = LineOnGlobeCache.get(globe);
251
+ this.circleProgram2d = CircleCache.get(globe);
252
+ this.circle3DProgram = Circle3DCache.get(globe);
253
+
254
+ // this.lineToTheOriginProgram = LineToTheOriginCache.get(globe);
255
+ const _circleFlatEdgeCount = this._circleFlatEdgeCount;
256
+ {
257
+ // createBuffers
258
+ const bufferType = "DYNAMIC_DRAW";
259
+ const initialCapacity = this.bufferOrchestrator.capacity;
260
+ this.bufferManagersCompMap = new Map(
261
+ [
262
+ ["centerCoords2d", {
263
+ 'bufferManager': new BufferManager(gl, 2, { bufferType, initialCapacity }),
264
+ 'adaptor': (item) => new Float32Array(globe.api_GetMercator2DPoint(item.long, item.lat)),
265
+ }],
266
+ ["centerCoords3d", {
267
+ 'bufferManager': new BufferManager(gl, 3, { bufferType, initialCapacity }),
268
+ 'adaptor': (item) => new Float32Array(globe.api_GetCartesian3DPoint(item.long, item.lat, 0, 0)),
269
+ }],
270
+ ["targetCoords2d", {
271
+ 'bufferManager': new BufferManager(gl, 2, { bufferType, initialCapacity }),
272
+ 'adaptor': (item) => new Float32Array(globe.api_GetMercator2DPoint(item.targetLong, item.targetLat)),
273
+ }],
274
+ ["targetCoords3d", {
275
+ 'bufferManager': new BufferManager(gl, 3, { bufferType, initialCapacity }),
276
+ 'adaptor': (item) => new Float32Array(globe.api_GetCartesian3DPoint(item.targetLong, item.targetLat, 0, 0)),
277
+ }],
278
+ ["rgba", {
279
+ 'bufferManager': new BufferManager(gl, 4, { bufferType, initialCapacity }),
280
+ 'adaptor': (item) => {
281
+ if (item.lineProperties?.rgba) return new Float32Array(item.lineProperties.rgba);
282
+ return new Float32Array(item.chainProperties.rgba);
283
+ }
284
+ }],
285
+ ["bigRadius", {
286
+ 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
287
+ 'adaptor': (item) => new Float32Array([item.bigRadius])
288
+ }],
289
+ ["dashRatio", {
290
+ 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
291
+ 'adaptor': (item) => new Float32Array([item.chainProperties.dashRatio])
292
+ }],
293
+ ["dashOpacity", {
294
+ 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
295
+ 'adaptor': (item) => new Float32Array([item.chainProperties.dashOpacity])
296
+ }],
297
+ ["circleDashAngle", {
298
+ 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
299
+ 'adaptor': (item) => {
300
+ if (item.circleProperties?.circleDashAngle) return new Float32Array([item.circleProperties.circleDashAngle / 360]);
301
+ return new Float32Array([item.chainProperties.circleDashAngle / 360]);
302
+ }
303
+ }],
304
+ ["rgbaCircle", {
305
+ "bufferManager": new BufferManager(gl, 4, { bufferType, initialCapacity }),
306
+ "adaptor": (item) => {
307
+ if (item.circleProperties?.rgba) return new Float32Array(item.circleProperties.rgba);
308
+ return new Float32Array(item.chainProperties.rgba);
309
+ }
310
+ }],
311
+ // Mercator buffers
312
+ ["circleDashAngleMercator", {
313
+ 'bufferManager': new BufferManager(gl, 1 * _circleFlatEdgeCount, { bufferType, initialCapacity }),
314
+ 'adaptor': (item) => {
315
+ if (item.circleProperties?.circleDashAngle) return new Float32Array([item.circleProperties.circleDashAngle / 360]);
316
+ return populateFloat32Array.fillFloat32Array(_circleFlatEdgeCount, item.chainProperties.circleDashAngle / 360);
317
+ }
318
+ }],
319
+ ["rgbaCircleMercator", { // 62
320
+ "bufferManager": new BufferManager(gl, 4 * _circleFlatEdgeCount, { bufferType, initialCapacity }),
321
+ "adaptor": (item) => {
322
+ if (item.circleProperties?.rgba) return populateFloat32Array.fillWithListData(_circleFlatEdgeCount, item.circleProperties.rgba);
323
+ return populateFloat32Array.fillWithListData(_circleFlatEdgeCount, item.chainProperties.rgba);
324
+ }
325
+ }],
326
+ ["dashOpacityMercator", {
327
+ 'bufferManager': new BufferManager(gl, 1 * _circleFlatEdgeCount, { bufferType, initialCapacity }),
328
+ 'adaptor': (item) => populateFloat32Array.fillFloat32Array(_circleFlatEdgeCount, item.chainProperties.dashOpacity)
329
+ }],
330
+ ["centerCoords2dMercator", {
331
+ 'bufferManager': new BufferManager(gl, 2 * _circleFlatEdgeCount, { bufferType, initialCapacity }),
332
+ 'adaptor': (item) => item.centerCoords2dflat,
333
+ }],
334
+ ]
335
+ );
336
+ const obj = function (bufferManagerComp) {
337
+ return { 'buffer': bufferManagerComp.bufferManager.buffer, 'stride': 0, 'offset': 0 }
338
+ };
339
+ this.lineVao = this.lineProgram.createVAO(
340
+ ...['centerCoords2d', 'centerCoords3d', 'targetCoords2d', 'targetCoords3d', 'dashRatio', 'dashOpacity', 'rgba'].map(key => obj(this.bufferManagersCompMap.get(key))));
341
+ this.circleVao2d = this.circleProgram2d.createVAO(
342
+ ...["centerCoords2dMercator", "rgbaCircleMercator", "circleDashAngleMercator", "dashOpacityMercator"].map(key => obj(this.bufferManagersCompMap.get(key))));
343
+ this.circle3DVao = this.circle3DProgram.createVAO(
344
+ ...["centerCoords3d", "bigRadius", "rgbaCircle", "circleDashAngle", "dashOpacity"].map(key => obj(this.bufferManagersCompMap.get(key)))
345
+ );
346
+
347
+ }
348
+
349
+ }
350
+
351
+
352
+
360
353
  _updateTexts(chainKeys, textWriterIDs) {
361
354
  if (textWriterIDs.length === 0) return;
362
- const textWriters = textWriterGetOrThrow(this._textContextWriterInjectionMap, textWriterIDs)
355
+ const textWriters = textWriterGetOrThrow(this._textWritersMap, textWriterIDs)
363
356
  chainKeys.forEach((chainKey) => {
364
357
  this._chainListMap.textUpdate(chainKey, textWriters, this._textDataPreAdaptor);
365
358
  })
@@ -419,7 +412,7 @@ export class CircleLineChainPlugin {
419
412
  CircleCache.release(this.globe);
420
413
  Circle3DCache.release(this.globe);
421
414
  LineToTheOriginCache.release(this.globe);
422
- this._textContextWriterInjectionMap.forEach((writer) => writer.free());
415
+ this._textWritersMap.forEach((writer) => writer.free());
423
416
  const { gl } = this;
424
417
  gl.deleteVertexArray(this.lineVao);
425
418
  gl.deleteVertexArray(this.circleVao2d);
@@ -434,7 +427,7 @@ export class CircleLineChainPlugin {
434
427
  const { gl, globe } = this;
435
428
  gl.disable(gl.DEPTH_TEST);
436
429
  this.lineProgram.draw(this.lineVao, this.bufferOrchestrator.length, this._opacity);
437
- this._textContextWriterInjectionMap.forEach((writer) => writer.draw());
430
+ this._textWritersMap.forEach((writer) => writer.draw());
438
431
  // this.lineToTheOriginProgram.draw(this.toOriginVao, this.bufferOrchestrator.length, this._opacity);
439
432
  const is3D = globe.api_GetCurrentGeometry() === 0;
440
433
  if (this._drawCircleOn) {
@@ -454,4 +447,4 @@ const radiusMethod = (globe) => (v, i, array) => {
454
447
  return globe.Math.GetDist3D(v.long, v.lat, array[i + 1].long, array[i + 1].lat)
455
448
  }
456
449
 
457
- const textWriterGetOrThrow = mapGetOrThrow("textWriterIds is invalid")
450
+ const textWriterGetOrThrow = mapGetOrThrow("textWriterIDs is invalid")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pirireis/webglobeplugins",
3
- "version": "0.6.30-c",
3
+ "version": "0.6.32-a",
4
4
  "main": "index.js",
5
5
  "author": "Toprak Nihat Deniz Ozturk",
6
6
  "license": "MIT"
@@ -48,7 +48,8 @@ export default class
48
48
  const { gl } = this;
49
49
  const ubo = gl.createBuffer();
50
50
  gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
51
- gl.bufferData(gl.UNIFORM_BUFFER, 184, gl.STREAM_DRAW);
51
+ // 184 bytes in reality. Overflow on linux for some reason. So, 200 bytes.
52
+ gl.bufferData(gl.UNIFORM_BUFFER, 200, gl.STREAM_DRAW);
52
53
  gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, ubo);
53
54
  gl.bindBuffer(gl.UNIFORM_BUFFER, null);
54
55
  return ubo;