@pirireis/webglobeplugins 0.8.6 → 0.8.7
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 +51 -43
- package/circle-line-chain/plugin.js +52 -44
- package/compass-rose/compass-rose-padding-flat.js +3 -0
- package/compassrose/compassrose.js +1 -8
- package/heatwave/isobar/plugin.js +4 -1
- package/heatwave/isobar/quadtreecontours.js +0 -2
- package/heatwave/plugins/heatwaveglobeshell.js +2 -0
- package/package.json +1 -1
- package/partialrings/goals.md +2 -0
- package/partialrings/plugin.js +2 -1
- package/point-glow-line-to-earth/draw-subset-obj.js +27 -0
- package/point-glow-line-to-earth/keymethod.js +0 -0
- package/point-glow-line-to-earth/plugin.js +439 -0
- package/point-glow-line-to-earth/types.js +26 -0
- package/point-heat-map/index.js +0 -3
- package/point-heat-map/plugin-webworker.js +4 -9
- package/point-heat-map/point-to-heat-map-flow.js +0 -6
- package/point-tracks/plugin.js +4 -4
- package/programs/arrowfield/logic.js +6 -4
- package/programs/arrowfield/object.js +1 -1
- package/programs/float2legendwithratio/object.js +5 -4
- package/programs/globe-util/is-globe-moved.js +27 -0
- package/programs/globeshell/wiggle/logic.js +3 -7
- package/programs/globeshell/wiggle/object.js +1 -2
- package/programs/line-on-globe/circle-accurate-3d.js +16 -23
- package/programs/line-on-globe/circle-accurate-flat.js +21 -21
- package/programs/line-on-globe/lines-color-instanced-flat.js +6 -7
- package/programs/line-on-globe/naive-accurate-flexible.js +239 -0
- package/programs/line-on-globe/to-the-surface.js +129 -0
- package/programs/picking/pickable-renderer.js +216 -0
- package/programs/point-on-globe/element-globe-surface-glow.js +168 -0
- package/programs/point-on-globe/element-point-glow.js +184 -0
- package/programs/point-on-globe/square-pixel-point.js +2 -4
- package/programs/programcache.js +9 -0
- package/programs/rings/partial-ring/piece-of-pie.js +1 -1
- package/programs/totems/camerauniformblock.js +23 -2
- package/rangerings/plugin.js +9 -6
- package/shaders/fragment-toy/firework.js +55 -0
- package/shaders/fragment-toy/singularity.js +59 -0
- package/types.js +16 -0
- package/util/account/single-attribute-buffer-management/buffer-manager.js +1 -5
- package/util/account/util.js +17 -7
- package/util/check/typecheck.js +11 -0
- package/util/gl-util/buffer/integrate-buffer.js +74 -0
- package/util/gl-util/draw-options/client.js +59 -0
- package/util/gl-util/draw-options/methods.js +46 -0
- package/util/gl-util/draw-options/types.js +18 -0
- package/util/gl-util/uniform-block/manager.js +176 -0
- package/util/gl-util/uniform-block/roadmap.md +70 -0
- package/util/gl-util/uniform-block/shader.js +0 -0
- package/util/gl-util/uniform-block/types.js +7 -0
- package/util/jshelpers/equality.js +17 -0
- package/util/picking/picker-displayer.js +1 -1
- package/util/programs/shapesonglobe.js +17 -19
- package/util/shaderfunctions/geometrytransformations.js +27 -63
- package/bearing-line/roadmap.md +0 -15
- package/point-heat-map/plugin.js +0 -132
- package/programs/line-on-globe/naive-accurate.js +0 -221
- package/programs/line-on-globe/to-the-origin.js +0 -164
- package/util/jshelpers/timemethods.js +0 -19
- /package/{programs/point-on-globe/element-draw-glow.js → point-glow-line-to-earth/adaptors.js} +0 -0
package/rangerings/plugin.js
CHANGED
|
@@ -52,11 +52,11 @@ import { mapGetOrThrow } from "../util/check/get";
|
|
|
52
52
|
import { populateFloat32Array } from "../util/jshelpers/data-filler";
|
|
53
53
|
import { RingAccount, ringBigPaddingKeyMethod, ringKeyMethod } from "./ring-account";
|
|
54
54
|
import { CirclePadding3DCache } from "../programs/line-on-globe/degree-padding-around-circle-3d";
|
|
55
|
-
import { LineOnGlobeCache } from '../programs/line-on-globe/naive-accurate';
|
|
55
|
+
import { LineOnGlobeCache } from '../programs/line-on-globe/naive-accurate-flexible';
|
|
56
56
|
import RangeRingAngleText from "./rangeringangletext";
|
|
57
57
|
import { Z_ALPHA_MODE } from "../programs/line-on-globe/util";
|
|
58
58
|
import { ENUM_HIDE } from "./enum";
|
|
59
|
-
|
|
59
|
+
import { opacityCheck, constraintFloat } from "../util/check/typecheck";
|
|
60
60
|
const CIRCLE_FLAT_EDGE_COUNT = 362; // 360 + 2 for closing the circle and a cutting point
|
|
61
61
|
|
|
62
62
|
|
|
@@ -274,7 +274,7 @@ class RangeRings {
|
|
|
274
274
|
* @method setOpacity @param { number } opacity
|
|
275
275
|
*/
|
|
276
276
|
setOpacity(opacity) {
|
|
277
|
-
|
|
277
|
+
opacityCheck(opacity);
|
|
278
278
|
this._opacity = opacity;
|
|
279
279
|
this.paddingTextPlugin?.setOpacity(opacity);
|
|
280
280
|
this._textWritersMap.forEach((writer) => writer.setOpacity(opacity));
|
|
@@ -378,6 +378,7 @@ class RangeRings {
|
|
|
378
378
|
);
|
|
379
379
|
|
|
380
380
|
const obj = function (bufferManagerComp, divisor = 1) {
|
|
381
|
+
if (bufferManagerComp === null) return null;
|
|
381
382
|
return { 'buffer': bufferManagerComp.bufferManager.buffer, 'stride': 0, 'offset': 0, divisor }
|
|
382
383
|
|
|
383
384
|
};
|
|
@@ -431,8 +432,9 @@ class RangeRings {
|
|
|
431
432
|
]
|
|
432
433
|
);
|
|
433
434
|
|
|
434
|
-
this._bigPadding3dFlatVAO = this._bigPadding3dFlatProgram.createVAO(
|
|
435
|
-
...["circlePoint", "circlePoint3d", "paddingPoint", "paddingPoint3d",
|
|
435
|
+
this._bigPadding3dFlatVAO = this._bigPadding3dFlatProgram.createVAO(//"dashRatio", "dashOpacity"
|
|
436
|
+
...["circlePoint", "circlePoint3d", "paddingPoint", "paddingPoint3d", null, null, "rgba",].map(key =>
|
|
437
|
+
(key === null) ? null : obj(this.bufferManagersCompMapPadding.get(key)))
|
|
436
438
|
);
|
|
437
439
|
|
|
438
440
|
this._padding3dOneDegreeVao = this._padding3dProgram.createVAO(
|
|
@@ -575,7 +577,8 @@ class RangeRings {
|
|
|
575
577
|
// _padding2dProgram.draw(bigPaddingVAO, paddingBufferOrchestrator.length, _opacity);
|
|
576
578
|
if (_oneDegreePadding) _padding2dProgram.draw(_oneDegree2DPaddingVao, bufferOrchestrator.length * CIRCLE_FLAT_EDGE_COUNT, _opacity, _zAlphaOnDegreePadding);
|
|
577
579
|
}
|
|
578
|
-
|
|
580
|
+
const drawOptions = { drawRange: { first: 0, count: bufferOrchestrator.length } };
|
|
581
|
+
_bigPadding3dFlatProgram.draw(_bigPadding3dFlatVAO, drawOptions, _opacity);
|
|
579
582
|
this._textWritersMap.forEach((textWriter) => textWriter.draw());
|
|
580
583
|
gl.enable(gl.DEPTH_TEST);
|
|
581
584
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export const firework = `
|
|
2
|
+
float firework(vec2 point_coord, float phase) {
|
|
3
|
+
float t = phase + 5.0;
|
|
4
|
+
float z = 6.0;
|
|
5
|
+
const int n = 53; // particle count
|
|
6
|
+
|
|
7
|
+
vec3 startColor = vec3(0.0, 0.64, 0.2);
|
|
8
|
+
vec3 endColor = vec3(0.06, 0.35, 0.85);
|
|
9
|
+
|
|
10
|
+
float startRadius = 0.84;
|
|
11
|
+
float endRadius = 1.6;
|
|
12
|
+
|
|
13
|
+
float power = 0.51;
|
|
14
|
+
float duration = 4.0;
|
|
15
|
+
|
|
16
|
+
vec2 v = z * (2.0 * point_coord - vec2(1.0) );
|
|
17
|
+
|
|
18
|
+
vec3 col = vec3(0.0);
|
|
19
|
+
vec2 pm = v.yx * 2.8;
|
|
20
|
+
|
|
21
|
+
float dMax = duration;
|
|
22
|
+
float evo = (sin(phase * 0.01 + 400.0) * 0.5 + 0.5) * 99.0 + 1.0;
|
|
23
|
+
|
|
24
|
+
float mb = 0.0;
|
|
25
|
+
float mbRadius = 0.0;
|
|
26
|
+
float sum = 0.0;
|
|
27
|
+
|
|
28
|
+
for(int i = 0; i < n; i++) {
|
|
29
|
+
float d = fract(t * power + 48934.4238 * sin(float(i / int(evo)) * 692.7398));
|
|
30
|
+
|
|
31
|
+
float a = 6.28 * float(i) / float(n);
|
|
32
|
+
float x = d * cos(a) * duration;
|
|
33
|
+
float y = d * sin(a) * duration;
|
|
34
|
+
|
|
35
|
+
float distRatio = d / dMax;
|
|
36
|
+
mbRadius = mix(startRadius, endRadius, distRatio);
|
|
37
|
+
|
|
38
|
+
vec2 p = v - vec2(x, y);
|
|
39
|
+
mb = mbRadius / dot(p, p);
|
|
40
|
+
|
|
41
|
+
sum += mb;
|
|
42
|
+
col = mix(col, mix(startColor, endColor, distRatio), mb / sum);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
sum /= float(n);
|
|
46
|
+
col = normalize(col) * sum;
|
|
47
|
+
sum = clamp(sum, 0.0, 0.4);
|
|
48
|
+
|
|
49
|
+
vec3 tex = vec3(1.0);
|
|
50
|
+
col *= smoothstep(tex, vec3(0.0), vec3(sum));
|
|
51
|
+
|
|
52
|
+
float alpha = sum * 2.5;
|
|
53
|
+
return clamp(alpha, 0.0, 1.0);
|
|
54
|
+
}
|
|
55
|
+
`
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
const singularity = `
|
|
4
|
+
|
|
5
|
+
vec3 palette(float d){
|
|
6
|
+
return mix(vec3(0.2, 0.7, 0.9), vec3(1.0, 0.0, 1.0), d);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
vec2 rotate(vec2 p, float a){
|
|
10
|
+
float c = cos(a);
|
|
11
|
+
float s = sin(a);
|
|
12
|
+
return p * mat2(c, s, -s, c);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
float map(vec3 p){
|
|
16
|
+
for (int i = 0; i < 4; ++i){
|
|
17
|
+
float t = u_phase * 0.2;
|
|
18
|
+
p.xz = rotate(p.xz, t);
|
|
19
|
+
p.xy = rotate(p.xy, t * 1.89);
|
|
20
|
+
p.xz = abs(p.xz);
|
|
21
|
+
p.xz -= 0.85;
|
|
22
|
+
}
|
|
23
|
+
return dot(sign(p), p) / 5.0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
vec4 rm(vec3 ro, vec3 rd){
|
|
27
|
+
float t = 0.0;
|
|
28
|
+
vec3 col = vec3(0.0);
|
|
29
|
+
float d;
|
|
30
|
+
for (float i = 0.0; i < 56.0; i++){
|
|
31
|
+
vec3 p = ro + rd * t;
|
|
32
|
+
d = map(p) * 0.5;
|
|
33
|
+
if (d < 0.02){
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
if (d > 100.0){
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
col += palette(length(p) * 0.1) / (400.0 * d);
|
|
40
|
+
t += d;
|
|
41
|
+
}
|
|
42
|
+
return vec4(col, 1.0 / d * 2.0 );
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
vec4 singularity(vec2 pointCoord, float u_phase) {
|
|
46
|
+
vec2 uv = (pointCoord - 0.5); // Normalized coordinates from gl_PointCoord
|
|
47
|
+
vec3 ro = vec3(0.0, 0.0, -50.0);
|
|
48
|
+
ro.xz = rotate(ro.xz, u_phase);
|
|
49
|
+
vec3 cf = normalize(-ro);
|
|
50
|
+
vec3 cs = normalize(cross(cf, vec3(0.0, 1.0, 0.0)));
|
|
51
|
+
vec3 cu = normalize(cross(cf, cs));
|
|
52
|
+
|
|
53
|
+
vec3 uuv = ro + cf * 3.0 + uv.x * cs + uv.y * cu;
|
|
54
|
+
vec3 rd = normalize(uuv - ro);
|
|
55
|
+
|
|
56
|
+
return rm(ro, rd);
|
|
57
|
+
}`;
|
|
58
|
+
|
|
59
|
+
export { singularity };
|
package/types.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef DrawRange
|
|
3
|
+
* @type {Object}
|
|
4
|
+
* @property {int} first
|
|
5
|
+
* @property {int} count
|
|
6
|
+
*
|
|
7
|
+
* @typedef DrawRangeIndexParamsClient
|
|
8
|
+
* @type {Object}
|
|
9
|
+
* @property {null|DrawRange} drawRange
|
|
10
|
+
* @property {null|Int32List} indexes
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* * @typedef {Array<number>} Color rgba color 0-1 values
|
|
16
|
+
*/
|
|
@@ -40,7 +40,6 @@ export class BufferManager {
|
|
|
40
40
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
41
41
|
for (let offset of offsets) {
|
|
42
42
|
if (offset !== undefined) {
|
|
43
|
-
|
|
44
43
|
gl.bufferSubData(gl.ARRAY_BUFFER, offset * offsetMultiplier, emptyBlock);
|
|
45
44
|
}
|
|
46
45
|
}
|
|
@@ -108,7 +107,4 @@ export class BufferManager {
|
|
|
108
107
|
this.gl = null;
|
|
109
108
|
this.isFreed = true;
|
|
110
109
|
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
110
|
+
}
|
package/util/account/util.js
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
|
-
export const vaoAttributeLoader = (gl, buffer,
|
|
2
|
-
if (
|
|
3
|
-
|
|
1
|
+
export const vaoAttributeLoader = (gl, buffer, index, size, stride, offset, divisor = null, type = null) => {
|
|
2
|
+
if (!gl || !buffer) {
|
|
3
|
+
throw new Error("Invalid WebGL context or buffer");
|
|
4
4
|
}
|
|
5
|
+
if (index < 0) {
|
|
6
|
+
throw new Error("Attribute index must be non-negative");
|
|
7
|
+
}
|
|
8
|
+
if (stride < 0 || offset < 0) {
|
|
9
|
+
throw new Error("Stride and offset must be non-negative");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const attribType = type === null ? gl.FLOAT : type;
|
|
5
13
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
6
|
-
gl.enableVertexAttribArray(
|
|
7
|
-
gl.vertexAttribPointer(
|
|
14
|
+
gl.enableVertexAttribArray(index);
|
|
15
|
+
gl.vertexAttribPointer(index, size, attribType, false, stride, offset);
|
|
8
16
|
if (divisor !== null) {
|
|
9
|
-
gl.vertexAttribDivisor(
|
|
17
|
+
gl.vertexAttribDivisor(index, divisor);
|
|
10
18
|
}
|
|
11
19
|
|
|
12
|
-
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
package/util/check/typecheck.js
CHANGED
|
@@ -26,3 +26,14 @@ export const isTextFont = (textFont) => {
|
|
|
26
26
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
export const constraintFloat = (x, lowerBound = null, upperBound = null) => {
|
|
30
|
+
if (typeof x !== "number") throw new Error("type must be numberic");
|
|
31
|
+
if (lowerBound === null && upperBound === null) return;
|
|
32
|
+
if (lowerBound !== null && lowerBound > x) throw new Error(`input must be greater than ${lowerBound}`);
|
|
33
|
+
if (upperBound !== null && x > upperBound) throw new Error(`input must be less than ${upperBound}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
export const isBoolean = (x) => {
|
|
38
|
+
if (typeof x !== "boolean") throw new TypeError("type must be boolean");
|
|
39
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @typedef BufferAndReadInfo Buffers can be intertwined or interleaved.
|
|
4
|
+
* This object forces user to adapt generic convention of buffer and read information.
|
|
5
|
+
* @type {Object}
|
|
6
|
+
* @property {WebGLBuffer} buffer
|
|
7
|
+
* @property {number} stride
|
|
8
|
+
* @property {number} offset
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* @param {WebGLBuffer} gl
|
|
14
|
+
* @param {BufferAndReadInfo} bufferAndReadInfo
|
|
15
|
+
* @param {number} index
|
|
16
|
+
* @param {number} size
|
|
17
|
+
* @param {Object} options
|
|
18
|
+
* @param {*} options.type | default gl.FLOAT, gl.UNSIGNED_BYTE, gl.SHORT, gl.UNSIGNED_SHORT, gl.INT, gl.UNSIGNED_INT
|
|
19
|
+
* @param {number} options.divisor
|
|
20
|
+
* @param {Array<number>} options.escapeValues
|
|
21
|
+
* @returns
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const attributeLoader = (gl, bufferAndReadInfo, index, size, { divisor = null, type = null, escapeValues = null, normalized = false } = {}) => {
|
|
25
|
+
if (size < 1 || size > 4) throw new Error("Size must be between 1 and 4");
|
|
26
|
+
if (bufferAndReadInfo == null) {
|
|
27
|
+
if (escapeValues !== null) constantFunction(gl, index, size, escapeValues);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const { buffer, stride, offset } = bufferAndReadInfo;
|
|
32
|
+
if (!gl || !buffer) {
|
|
33
|
+
throw new Error("Invalid WebGL context or buffer");
|
|
34
|
+
}
|
|
35
|
+
if (index < 0) {
|
|
36
|
+
throw new Error("Attribute index must be non-negative");
|
|
37
|
+
}
|
|
38
|
+
if (stride < 0 || offset < 0) {
|
|
39
|
+
throw new Error("Stride and offset must be non-negative");
|
|
40
|
+
}
|
|
41
|
+
console.log("stride", stride, "offset", offset);
|
|
42
|
+
const attribType = type === null ? gl.FLOAT : type;
|
|
43
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
44
|
+
gl.enableVertexAttribArray(index);
|
|
45
|
+
gl.vertexAttribPointer(index, size, attribType, normalized, stride, offset);
|
|
46
|
+
if (divisor !== null) {
|
|
47
|
+
gl.vertexAttribDivisor(index, divisor);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
*
|
|
54
|
+
* @param {WebGLBuffer} buffer
|
|
55
|
+
* @param {number} stride
|
|
56
|
+
* @param {number} offset
|
|
57
|
+
* @returns {BufferAndReadInfo}
|
|
58
|
+
*/
|
|
59
|
+
const createBufferAndReadInfo = (buffer, stride = 0, offset = 0) => {
|
|
60
|
+
if (buffer == null) return null;
|
|
61
|
+
console.log("createBufferAndReadInfo", buffer, stride, offset);
|
|
62
|
+
return { buffer, stride, offset };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
const constantFunction = (gl, index, size, escapeValues) => {
|
|
68
|
+
const func = `vertexAttrib${size}f`;
|
|
69
|
+
console.log(`Using constant function ${func}`, gl[func], escapeValues);
|
|
70
|
+
gl[func](index, ...escapeValues);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
export { attributeLoader, createBufferAndReadInfo };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
class DrawOptionsClient {
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef DrawOptionsClientAdaptor
|
|
7
|
+
* @type {Object}
|
|
8
|
+
* @property {function} setElements
|
|
9
|
+
* @property {function} setDrawRange
|
|
10
|
+
* @property {function} free
|
|
11
|
+
*
|
|
12
|
+
* @param {*} gl
|
|
13
|
+
* @param {*} adaptorsMap
|
|
14
|
+
*/
|
|
15
|
+
constructor(gl, adaptorsMap) {
|
|
16
|
+
this.gl = gl;
|
|
17
|
+
this.adaptorsMap = adaptorsMap;
|
|
18
|
+
this.elementBuffers = new Map();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
__init() {
|
|
22
|
+
const { gl, adaptorsMap } = this;
|
|
23
|
+
// create element buffer for each element buffer type
|
|
24
|
+
for (const [key, value] of Object.entries(adaptorsMap)) {
|
|
25
|
+
const elementBuffer = gl.createBuffer();
|
|
26
|
+
this.elementBuffers.set(key, elementBuffer);
|
|
27
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
|
|
28
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, value, gl.DYNAMIC_DRAW);
|
|
29
|
+
}
|
|
30
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
setDrawRange() {
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
*
|
|
43
|
+
* @param {null|Int32List|Int32Array} elementIndexes
|
|
44
|
+
*/
|
|
45
|
+
setElements(elementIndexes = null) {
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
getDrawOptions() {
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
free() {
|
|
57
|
+
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import './types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {WebGL2RenderingContext} gl
|
|
6
|
+
* @param {WebGL2RenderingContext.DrawMode} mode
|
|
7
|
+
* @param {DrawRangeIndexParams} drawOptions
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
// first and element effects the vertexID, which is unfortunately not effected
|
|
12
|
+
const drawInstanced = (gl, mode, drawOptions, vertexCount) => {
|
|
13
|
+
const { drawRange, indexType = gl.UNSIGNED_INT } = drawOptions;
|
|
14
|
+
const { first = 0, count: instanceCount = 1 } = drawRange;
|
|
15
|
+
if (first > 0 || drawOptions.elementBuffer) {
|
|
16
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, drawOptions.elementBuffer);
|
|
17
|
+
gl.drawElementsInstanced(mode, vertexCount, indexType, first, instanceCount);
|
|
18
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
|
|
19
|
+
} else {
|
|
20
|
+
|
|
21
|
+
gl.drawArraysInstanced(mode, first, vertexCount, instanceCount);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
*
|
|
28
|
+
* @param {WebGL2RenderingContext} gl
|
|
29
|
+
* @param {WebGL2RenderingContext.DrawMode} defaultMode
|
|
30
|
+
* @param {DrawRangeIndexParams} drawOptions
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
const drawArrays = (gl, defaultMode, drawOptions) => {
|
|
34
|
+
const { drawRange, elementBuffer, indexType = gl.UNSIGNED_INT, drawMode = null } = drawOptions;
|
|
35
|
+
const { first, count } = drawRange;
|
|
36
|
+
const mode = drawMode ?? defaultMode;
|
|
37
|
+
if (elementBuffer) {
|
|
38
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
|
|
39
|
+
gl.drawElements(mode, count, indexType, first);
|
|
40
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
|
|
41
|
+
} else {
|
|
42
|
+
gl.drawArrays(mode, first, count);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { drawArrays, drawInstanced }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef DrawRange
|
|
3
|
+
* @type {Object}
|
|
4
|
+
* @property {int} first
|
|
5
|
+
* @property {int} count
|
|
6
|
+
*
|
|
7
|
+
* @typedef DrawRangeIndexParams
|
|
8
|
+
* @type {Object}
|
|
9
|
+
* @property {null|DrawRange} drawRange
|
|
10
|
+
* @property {null|ElementBuffer} elementBuffer
|
|
11
|
+
* @property {null|indexType} indexType
|
|
12
|
+
* @property {null|int} drawMode
|
|
13
|
+
*
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import "./types";
|
|
2
|
+
|
|
3
|
+
const typeSizes = {
|
|
4
|
+
'float': 4,
|
|
5
|
+
'vec2': 8,
|
|
6
|
+
'vec3': 16, // vec3 takes up same space as vec4 due to alignment
|
|
7
|
+
'vec4': 16,
|
|
8
|
+
'mat2': 32, // 2 vec4s (16 * 2)
|
|
9
|
+
'mat3': 48, // 3 vec4s (16 * 3)
|
|
10
|
+
'mat4': 64, // 4 vec4s (16 * 4)
|
|
11
|
+
'int': 4,
|
|
12
|
+
'ivec2': 8,
|
|
13
|
+
'ivec3': 16,
|
|
14
|
+
'ivec4': 16,
|
|
15
|
+
'bool': 4
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const typeAlignments = {
|
|
19
|
+
'float': 4,
|
|
20
|
+
'vec2': 8,
|
|
21
|
+
'vec3': 16,
|
|
22
|
+
'vec4': 16,
|
|
23
|
+
'mat2': 16, // aligns to vec4 boundary
|
|
24
|
+
'mat3': 16, // aligns to vec4 boundary
|
|
25
|
+
'mat4': 16, // aligns to vec4 boundary
|
|
26
|
+
'int': 4,
|
|
27
|
+
'ivec2': 8,
|
|
28
|
+
'ivec3': 16,
|
|
29
|
+
'ivec4': 16,
|
|
30
|
+
'bool': 4
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
const typeArrayConstructors = {
|
|
35
|
+
'float': Float32Array,
|
|
36
|
+
'vec2': Float32Array,
|
|
37
|
+
'vec3': Float32Array,
|
|
38
|
+
'vec4': Float32Array,
|
|
39
|
+
'mat2': Float32Array,
|
|
40
|
+
'mat3': Float32Array,
|
|
41
|
+
'mat4': Float32Array,
|
|
42
|
+
'int': Int32Array,
|
|
43
|
+
'ivec2': Int32Array,
|
|
44
|
+
'ivec3': Int32Array,
|
|
45
|
+
'ivec4': Int32Array,
|
|
46
|
+
'bool': Float32Array
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class UniformBlockManager {
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
*
|
|
54
|
+
* @param {UniformBlockName} blockName
|
|
55
|
+
* @param {Array<UniformBlockMember} blockMembers
|
|
56
|
+
* @param {string} prefix usage name of block in the shader
|
|
57
|
+
*/
|
|
58
|
+
constructor(blockName, blockMembers, bindingPoint, prefix = "") {
|
|
59
|
+
this.blockName = blockName;
|
|
60
|
+
this.blockMembers = blockMembers;
|
|
61
|
+
this.bindingPoint = bindingPoint;
|
|
62
|
+
this.prefix = prefix;
|
|
63
|
+
this.offsetMap = this.__create_LayoutSTD140_OffsetMap();
|
|
64
|
+
this.size = this.__calculateSize();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
glslCode() {
|
|
70
|
+
let code = `layout(std140) uniform ${this.blockName} {`;
|
|
71
|
+
for (const member of this.blockMembers) {
|
|
72
|
+
const { name, type } = member;
|
|
73
|
+
code += `${type} ${this.prefix}${name};`;
|
|
74
|
+
}
|
|
75
|
+
if (this.prefix) {
|
|
76
|
+
code += `} ${this.prefix};`;
|
|
77
|
+
} else {
|
|
78
|
+
code += `};`;
|
|
79
|
+
}
|
|
80
|
+
return code;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
createUBO(gl, bufferWriteType = "STATIC_DRAW") {
|
|
85
|
+
const ubo = gl.createBuffer();
|
|
86
|
+
gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
|
|
87
|
+
gl.bufferData(gl.UNIFORM_BUFFER, this.size, gl[bufferWriteType]);
|
|
88
|
+
gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, ubo);
|
|
89
|
+
|
|
90
|
+
for (const member of this.blockMembers) {
|
|
91
|
+
const { name, type, value = null } = member;;
|
|
92
|
+
const offset = this.offsetMap.get(name);
|
|
93
|
+
const data = (value === null) ? new typeArrayConstructors[type](typeSizes[type] / 4).fill(NaN) : value;
|
|
94
|
+
gl.bufferSubData(gl.UNIFORM_BUFFER, offset, data);
|
|
95
|
+
}
|
|
96
|
+
gl.bindBuffer(gl.UNIFORM_BUFFER, null);
|
|
97
|
+
|
|
98
|
+
return { // TODO typedef this, encapsulate this in a class or something, ask ai
|
|
99
|
+
ubo,
|
|
100
|
+
update: this.updateUBO.bind(this, gl, ubo),
|
|
101
|
+
bind: this.bind.bind(this, gl, ubo),
|
|
102
|
+
unbind: this.unbind.bind(this, gl),
|
|
103
|
+
free: () => gl.deleteBuffer(ubo)
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
updateUBO(gl, ubo, nameValueMap) {
|
|
109
|
+
gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
|
|
110
|
+
for (const [name, value] of nameValueMap.entries()) {
|
|
111
|
+
const offset = this.offsetMap.get(name);
|
|
112
|
+
const type = this.blockMembers.find(member => member.name === name).type;
|
|
113
|
+
if (offset === undefined) {
|
|
114
|
+
throw new Error(`Uniform block member ${name} not found in offset map.`);
|
|
115
|
+
}
|
|
116
|
+
let data;
|
|
117
|
+
if (Array.isArray(value)) {
|
|
118
|
+
data = new typeArrayConstructors[type](value);
|
|
119
|
+
} else if (typeof value === 'number') {
|
|
120
|
+
data = new typeArrayConstructors[type]([value]);
|
|
121
|
+
} else if (value instanceof ArrayBuffer) {
|
|
122
|
+
data = new typeArrayConstructors[type](value);
|
|
123
|
+
} else if (ArrayBuffer.isView(value) && !(value instanceof DataView))
|
|
124
|
+
data = (typeof value === 'number') ? new typeArrayConstructors[type]([value]) : new typeArrayConstructors[type](value);
|
|
125
|
+
else {
|
|
126
|
+
throw new Error(`Unsupported value type for ${name}: ${typeof value}`);
|
|
127
|
+
}
|
|
128
|
+
gl.bufferSubData(gl.UNIFORM_BUFFER, offset, data);
|
|
129
|
+
}
|
|
130
|
+
gl.bindBuffer(gl.UNIFORM_BUFFER, null);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// call this after linking the program
|
|
134
|
+
assignBindingPoint(gl, program) {
|
|
135
|
+
const blockIndex = gl.getUniformBlockIndex(program, this.blockName);
|
|
136
|
+
gl.uniformBlockBinding(program, blockIndex, this.bindingPoint);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// call this before drawing
|
|
140
|
+
bind(gl, ubo) {
|
|
141
|
+
gl.bindBufferBase(gl.UNIFORM_BUFFER, this.bindingPoint, ubo);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// call this right after drawing
|
|
145
|
+
unbind(gl) {
|
|
146
|
+
gl.bindBufferBase(gl.UNIFORM_BUFFER, this.bindingPoint, null);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
// implicit methods
|
|
151
|
+
__create_LayoutSTD140_OffsetMap() {
|
|
152
|
+
let offset = 0;
|
|
153
|
+
const offsetMap = new Map();
|
|
154
|
+
for (const member of this.blockMembers) {
|
|
155
|
+
const { name, type } = member;
|
|
156
|
+
const size = typeSizes[type];
|
|
157
|
+
const alignment = typeAlignments[type];
|
|
158
|
+
const padding = (alignment - (offset % alignment)) % alignment;
|
|
159
|
+
offset += padding;
|
|
160
|
+
offsetMap.set(name, offset);
|
|
161
|
+
offset += size;
|
|
162
|
+
}
|
|
163
|
+
return offsetMap;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// __create_LayoutSTD140_OffsetMap() should be called before this
|
|
167
|
+
__calculateSize() {
|
|
168
|
+
const lastOffset = Array.from(this.offsetMap.values()).pop();
|
|
169
|
+
const lastItemAlignment = typeAlignments[this.blockMembers[this.blockMembers.length - 1].type];
|
|
170
|
+
return lastOffset + lastItemAlignment;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
export { UniformBlockManager };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# UniformBlock Wrapper
|
|
2
|
+
|
|
3
|
+
- Uniform shader string
|
|
4
|
+
- bind/unbind
|
|
5
|
+
- set/get uniform value generic
|
|
6
|
+
|
|
7
|
+
## INPUT
|
|
8
|
+
- uniform block name
|
|
9
|
+
- Array<{type, name}> UniformBlockMembers
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## PROCESS
|
|
13
|
+
|
|
14
|
+
- Calculate and save starting offset of each member
|
|
15
|
+
- Create UBO
|
|
16
|
+
- Bind UBO
|
|
17
|
+
- Set uniform value
|
|
18
|
+
|
|
19
|
+
### Calculate and save starting offset of each member
|
|
20
|
+
|
|
21
|
+
layout(std140) is a convention. The calculation should be done according to this convention.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
type | size
|
|
25
|
+
--- | ---
|
|
26
|
+
float | 4
|
|
27
|
+
vec2 | 8
|
|
28
|
+
vec3 | 12
|
|
29
|
+
vec4 | 16
|
|
30
|
+
mat2 | 16
|
|
31
|
+
mat3 | 48
|
|
32
|
+
mat4 | 64
|
|
33
|
+
|
|
34
|
+
A line is 16 bytes aligned. Alignment can be shared if previous member is equal or bigger then the next member and the sum of the sizes are smaller then 16 bytes.
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
## setMethod
|
|
46
|
+
|
|
47
|
+
update({
|
|
48
|
+
color = null,
|
|
49
|
+
bboxOffsetRad = null,
|
|
50
|
+
bboxSizeRad = null,
|
|
51
|
+
resolution = null,
|
|
52
|
+
tailLengthRatio = null,
|
|
53
|
+
wingLengthRatio = null,
|
|
54
|
+
height = null,
|
|
55
|
+
opacity = null,
|
|
56
|
+
noDataValue = null,
|
|
57
|
+
} = {}) {
|
|
58
|
+
const { gl, ubo } = this;
|
|
59
|
+
gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
|
|
60
|
+
if (color !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array(color));
|
|
61
|
+
if (opacity !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 12, new Float32Array([opacity]));
|
|
62
|
+
if (bboxOffsetRad !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 16, new Float32Array(bboxOffsetRad));
|
|
63
|
+
if (bboxSizeRad !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 24, new Float32Array(bboxSizeRad));
|
|
64
|
+
if (resolution !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 32, new Float32Array(resolution));
|
|
65
|
+
if (tailLengthRatio !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 40, new Float32Array([tailLengthRatio]));
|
|
66
|
+
if (wingLengthRatio !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 44, new Float32Array([wingLengthRatio]));
|
|
67
|
+
if (height !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 48, new Float32Array([height]));
|
|
68
|
+
if (noDataValue !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 52, new Float32Array([noDataValue]));
|
|
69
|
+
gl.bindBuffer(gl.UNIFORM_BUFFER, null);
|
|
70
|
+
}
|