@pirireis/webglobeplugins 0.17.1 → 1.0.3

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.
Files changed (67) hide show
  1. package/Math/haversine.js +22 -0
  2. package/Math/methods.js +15 -2
  3. package/Math/tessellation/methods.js +4 -1
  4. package/Math/tessellation/nearest-value-padding.js +112 -0
  5. package/Math/tessellation/spherical-triangle-area.js +99 -0
  6. package/Math/tessellation/tile-merger.js +346 -215
  7. package/Math/tessellation/triangle-tessellation.js +381 -9
  8. package/Math/vec3.js +4 -0
  9. package/Math/xyz-tile.js +18 -0
  10. package/altitude-locator/plugin.js +1 -2
  11. package/investigation-tools/draw/tiles/adapters.js +2 -2
  12. package/investigation-tools/draw/tiles/tiles.js +2 -2
  13. package/package.json +1 -1
  14. package/programs/helpers/fadeaway.js +6 -1
  15. package/programs/point-on-globe/square-pixel-point.js +1 -0
  16. package/programs/polygon-on-globe/texture-dem-triangles.js +94 -116
  17. package/programs/totems/camera-totem-attactment-interface.js +1 -0
  18. package/programs/totems/camerauniformblock.js +33 -22
  19. package/programs/totems/dem-textures-manager.js +265 -0
  20. package/programs/vectorfields/logics/drawrectangleparticles.js +51 -18
  21. package/programs/vectorfields/logics/{ubo-new.js → particle-ubo.js} +5 -14
  22. package/programs/vectorfields/logics/pixelbased.js +42 -36
  23. package/programs/vectorfields/pingpongbuffermanager.js +34 -8
  24. package/semiplugins/shape-on-terrain/terrain-polygon/adapters.js +55 -0
  25. package/semiplugins/shape-on-terrain/terrain-polygon/data/cache.js +102 -0
  26. package/semiplugins/shape-on-terrain/terrain-polygon/data/index-polygon-map.js +45 -0
  27. package/semiplugins/shape-on-terrain/terrain-polygon/data/manager.js +4 -0
  28. package/semiplugins/shape-on-terrain/terrain-polygon/data/master-worker.js +177 -0
  29. package/semiplugins/shape-on-terrain/terrain-polygon/data/polygon-to-triangles.js +100 -0
  30. package/semiplugins/shape-on-terrain/terrain-polygon/data/random.js +121 -0
  31. package/semiplugins/shape-on-terrain/terrain-polygon/data/types.js +1 -0
  32. package/semiplugins/shape-on-terrain/terrain-polygon/data/worker-contact.js +63 -0
  33. package/semiplugins/shape-on-terrain/terrain-polygon/data/worker.js +125 -0
  34. package/semiplugins/shape-on-terrain/terrain-polygon/terrain-polygon.js +219 -0
  35. package/semiplugins/shape-on-terrain/terrain-polygon/types.js +8 -0
  36. package/semiplugins/shell/bbox-renderer/logic.js +18 -58
  37. package/semiplugins/shell/bbox-renderer/object.js +19 -9
  38. package/tracks/point-heat-map/point-to-heat-map-flow.js +1 -1
  39. package/tracks/point-tracks/plugin.js +13 -6
  40. package/tracks/timetracks/program-line-strip.js +1 -1
  41. package/util/account/single-attribute-buffer-management/buffer-manager.js +5 -3
  42. package/util/account/single-attribute-buffer-management/buffer-orchestrator.js +2 -2
  43. package/util/gl-util/uniform-block/manager.js +20 -10
  44. package/util/helper-methods.js +8 -0
  45. package/util/picking/fence.js +4 -2
  46. package/util/picking/picker-displayer.js +51 -9
  47. package/util/programs/draw-texture-on-canvas.js +18 -15
  48. package/util/shaderfunctions/geometrytransformations.js +67 -1
  49. package/vectorfield/waveparticles/plugin.js +241 -116
  50. package/vectorfield/wind/adapters/image-to-fields.js +61 -0
  51. package/vectorfield/wind/adapters/types.js +1 -0
  52. package/vectorfield/wind/imagetovectorfieldandmagnitude.js +6 -9
  53. package/vectorfield/wind/plugin-persistant copy.js +364 -0
  54. package/vectorfield/wind/plugin-persistant.js +375 -0
  55. package/vectorfield/wind/plugin.js +1 -1
  56. package/Math/tessellation/earcut/adapters.js +0 -37
  57. package/Math/tessellation/hybrid-triangle-tessellation-meta.js +0 -123
  58. package/Math/tessellation/shred-input.js +0 -18
  59. package/Math/tessellation/tiler.js +0 -50
  60. package/Math/tessellation/triangle-tessellation-meta.js +0 -523
  61. package/programs/polygon-on-globe/texture-dem-triangle-test-plugin-triangle.js +0 -328
  62. package/programs/vectorfields/logics/drawrectangleparticles1.js +0 -112
  63. package/semiplugins/shape-on-terrain/terrain-cover/texture-dem-cover.js +0 -1
  64. package/util/gl-util/uniform-block/types.js +0 -1
  65. package/util/webglobe/index.js +0 -2
  66. /package/Math/tessellation/{zoom-catch.js → constants.js} +0 -0
  67. /package/util/{webglobe/gldefaultstates.js → globe-default-gl-states.js} +0 -0
@@ -0,0 +1,265 @@
1
+ import { mergeMeshes } from "../../Math/tessellation/tile-merger";
2
+ import { globeBBoxToXYBBOX } from "../../Math/methods";
3
+ import { noRegisterGlobeProgramCache } from "../programcache";
4
+ import { CameraUniformBlockTotemCache } from "./camerauniformblock";
5
+ export const DEM_TEXTURE_BLOCK_STRING = `
6
+ layout(std140) uniform DemTextureUniformBlock {
7
+ vec4 u_demTextureBBOX[6]; // 96 bytes
8
+ vec4 u_textureDataCoverRatio[6]; // 96 bytes
9
+ vec2 u_textureResolution; // 8 bytes
10
+ int u_breakLoopIndex; // 4 bytes
11
+ };
12
+ uniform sampler2DArray u_demTexture;
13
+ `;
14
+ const MAXLAYERS = 6;
15
+ // Size calculation:
16
+ // BBOX: 6 * 16 bytes = 96
17
+ // CoverRatio: 6 * 16 bytes = 96
18
+ // Resolution: 8 bytes (offset 192)
19
+ // BreakLoopIndex: 4 bytes (offset 200)
20
+ // Total used: 204 bytes.
21
+ // std140 blocks are typically padded to 16 bytes alignment -> 208 bytes.
22
+ // 208 bytes / 4 bytes per float = 52 floats.
23
+ const uniformBlockData = new Float32Array(52);
24
+ function drawnedTilesHash(drawnTiles) {
25
+ let hash = 0;
26
+ for (const tile of drawnTiles) {
27
+ // Combine tile coordinates into a unique value
28
+ const val = (tile.level << 20) | (tile.x << 10) | tile.y;
29
+ hash = ((hash << 5) - hash) + val;
30
+ hash = hash | 0; // Convert to 32-bit integer
31
+ }
32
+ return hash;
33
+ }
34
+ function resCalculation(sourceResolution, mergeCount) {
35
+ return sourceResolution + (mergeCount - 1) * (sourceResolution - 1);
36
+ }
37
+ export class DemTextureManager {
38
+ _globe;
39
+ _mergeParameters = {
40
+ mergeCount: 20,
41
+ tileDimensionLength: 5,
42
+ processLimit: 6
43
+ };
44
+ STOP = false;
45
+ mergedData = [];
46
+ uniformBuffer = null;
47
+ demTexture = null;
48
+ textureWidth;
49
+ textureHeight;
50
+ cameraBlockTotem = null;
51
+ tilesHash = 0;
52
+ registry = new Set();
53
+ constructor(globe, { mergeCount = 20, tileDimensionLength = 5, processLimit = 6 } = {}) {
54
+ this._globe = globe;
55
+ this._mergeParameters.mergeCount = mergeCount;
56
+ this._mergeParameters.tileDimensionLength = tileDimensionLength;
57
+ this._mergeParameters.processLimit = processLimit;
58
+ this.textureWidth = this.textureHeight = resCalculation(tileDimensionLength, mergeCount);
59
+ this.cameraBlockTotem = CameraUniformBlockTotemCache.get(this._globe);
60
+ this.cameraBlockTotem.registerAttachment(this);
61
+ // Initialize uniform data buffer
62
+ this.initializeUniformBlock();
63
+ this.initializeTextureArray();
64
+ }
65
+ initializeUniformBlock() {
66
+ const gl = this._globe.gl;
67
+ if (!gl)
68
+ return;
69
+ // Create uniform buffer
70
+ this.uniformBuffer = gl.createBuffer();
71
+ gl.bindBuffer(gl.UNIFORM_BUFFER, this.uniformBuffer);
72
+ // Allocate buffer with correct size (52 floats * 4 bytes)
73
+ gl.bufferData(gl.UNIFORM_BUFFER, uniformBlockData.byteLength, gl.STREAM_COPY);
74
+ gl.bindBuffer(gl.UNIFORM_BUFFER, null);
75
+ }
76
+ initializeTextureArray() {
77
+ const gl = this._globe.gl;
78
+ if (!gl)
79
+ return;
80
+ // Create texture array
81
+ this.demTexture = gl.createTexture();
82
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.demTexture);
83
+ // Calculate correct size: tileDimensionLength + (mergeCount - 1) * (tileDimensionLength - 1)
84
+ // For tileDimensionLength=5, mergeCount=8: 5 + 7*4 = RESOLUTION
85
+ // gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.R32F, this.textureWidth, this.textureHeight, 6);
86
+ // // Allocate storage for texture array
87
+ gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, // mip level
88
+ gl.R32F, // internal format (32-bit float for DEM data)
89
+ this.textureWidth, this.textureHeight, MAXLAYERS, // number of layers
90
+ 0, // border
91
+ gl.RED, // format
92
+ gl.FLOAT, // type
93
+ null // data (null to allocate)
94
+ );
95
+ const ext = gl.getExtension('OES_texture_float_linear');
96
+ if (!ext) {
97
+ throw new Error("OES_texture_float_linear extension is supported.");
98
+ }
99
+ // Set texture parameters
100
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
101
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
102
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
103
+ gl.texParameteri(gl.TEXTURE_2D_ARRAY, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
104
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, null);
105
+ }
106
+ assignBindingPoint(program, bindingPoint) {
107
+ const gl = this._globe.gl;
108
+ if (!gl || !this.uniformBuffer || !program) {
109
+ console.warn('Cannot bind uniform block: missing GL context, buffer, or program');
110
+ return false;
111
+ }
112
+ const uniformBlockIndex = gl.getUniformBlockIndex(program, 'DemTextureUniformBlock');
113
+ if (uniformBlockIndex === gl.INVALID_INDEX) {
114
+ // Uniform block might be optimized out - this is not necessarily an error
115
+ console.warn(`Uniform block 'DemTextureUniformBlock' not found in program (may be optimized out)`);
116
+ return false;
117
+ }
118
+ gl.uniformBlockBinding(program, uniformBlockIndex, bindingPoint);
119
+ return true;
120
+ }
121
+ register(obj) {
122
+ this.registry.add(obj);
123
+ obj.setMergedTiles(this.mergedData);
124
+ }
125
+ unregister(obj) {
126
+ this.registry.delete(obj);
127
+ }
128
+ update() {
129
+ if (this.STOP)
130
+ return;
131
+ const gl = this._globe.gl;
132
+ const tilesMetaData = this._globe.api_GetVisibleTilesInfo();
133
+ const newHash = drawnedTilesHash(tilesMetaData);
134
+ if (this.tilesHash === newHash) {
135
+ return; // No change in drawn tiles, skip update
136
+ }
137
+ this.tilesHash = newHash;
138
+ this.mergedData = mergeMeshes(tilesMetaData, this._mergeParameters.mergeCount, this._mergeParameters.tileDimensionLength, this._mergeParameters.processLimit, this._globe);
139
+ // Bind texture before updating
140
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.demTexture);
141
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
142
+ // turn off premultiply alpha
143
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
144
+ for (let i = 0; i < this.mergedData.length; i++) {
145
+ const { mesh, bbox, coverRatio } = this.mergedData[i];
146
+ gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, // mip level
147
+ 0, // xoffset
148
+ 0, // yoffset
149
+ i, // zoffset (layer index)
150
+ this.textureWidth, this.textureHeight, 1, // depth (1 layer)
151
+ gl.RED, gl.FLOAT, mesh);
152
+ const bboxXY = globeBBoxToXYBBOX(bbox);
153
+ uniformBlockData[i * 4 + 0] = bboxXY.ll[0];
154
+ uniformBlockData[i * 4 + 1] = bboxXY.ll[1];
155
+ uniformBlockData[i * 4 + 2] = bboxXY.ur[0];
156
+ uniformBlockData[i * 4 + 3] = bboxXY.ur[1];
157
+ uniformBlockData[24 + i * 4 + 0] = coverRatio.x;
158
+ uniformBlockData[24 + i * 4 + 1] = coverRatio.y;
159
+ }
160
+ // Set resolution (offset 192 bytes -> index 48)
161
+ uniformBlockData[48] = this.textureWidth;
162
+ uniformBlockData[49] = this.textureHeight;
163
+ // Set break loop index (offset 200 bytes -> index 50)
164
+ uniformBlockData[50] = this.mergedData.length;
165
+ // Unbind texture after updating
166
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, null);
167
+ gl.bindBuffer(gl.UNIFORM_BUFFER, this.uniformBuffer);
168
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, uniformBlockData);
169
+ gl.bindBuffer(gl.UNIFORM_BUFFER, null);
170
+ for (const obj of this.registry) {
171
+ obj.setMergedTiles(this.mergedData);
172
+ }
173
+ }
174
+ bindData(textureUnit, bindingPoint) {
175
+ const gl = this._globe.gl;
176
+ if (!gl)
177
+ return;
178
+ // Bind uniform buffer
179
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, bindingPoint, this.uniformBuffer);
180
+ // Bind texture array
181
+ gl.activeTexture(gl.TEXTURE0 + textureUnit);
182
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, this.demTexture);
183
+ }
184
+ find(x, y, zoom) {
185
+ for (const data of this._globe.api_GetVisibleTilesInfo()) {
186
+ if (data.x === x && data.y === y && data.level === zoom) {
187
+ return data;
188
+ }
189
+ }
190
+ return null;
191
+ }
192
+ showMergedDataInfo(zoomLevel) {
193
+ if (!this.mergedData[zoomLevel]) {
194
+ console.log(`No merged data at zoom level ${zoomLevel}`);
195
+ return;
196
+ }
197
+ const { textureHeight, textureWidth } = this;
198
+ const { mesh, bbox, coverRatio } = this.mergedData[zoomLevel];
199
+ const result = [];
200
+ const xLength = Math.ceil(mesh.length / textureHeight * coverRatio.x);
201
+ const yLength = Math.ceil(mesh.length / textureWidth * coverRatio.y);
202
+ for (let y = 0; y < yLength; y++) {
203
+ const row = [];
204
+ for (let x = 0; x < xLength; x++) {
205
+ const index = y * textureWidth + x;
206
+ const value = mesh[index];
207
+ row.push(value);
208
+ }
209
+ result.push(new Float32Array(row));
210
+ }
211
+ return { mesh: result, bbox: bbox, coverRatio: coverRatio };
212
+ }
213
+ unbindData(textureUnit, bindingPoint) {
214
+ const gl = this._globe.gl;
215
+ if (!gl)
216
+ return;
217
+ // Unbind texture array
218
+ gl.activeTexture(gl.TEXTURE0 + textureUnit);
219
+ // Unbind
220
+ gl.bindTexture(gl.TEXTURE_2D_ARRAY, null);
221
+ // call this right after drawing
222
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, bindingPoint, null);
223
+ }
224
+ get() {
225
+ return this.mergedData;
226
+ }
227
+ getBBoxes() {
228
+ const ressult = new Array(this.mergedData.length);
229
+ for (let i = 0; i < this.mergedData.length; i++) {
230
+ const { bbox, zoom } = this.mergedData[i];
231
+ ressult[i] = {
232
+ minX: bbox.ll.x,
233
+ minY: bbox.ll.y,
234
+ maxX: bbox.ur.x,
235
+ maxY: bbox.ur.y,
236
+ zoom
237
+ };
238
+ }
239
+ return ressult;
240
+ }
241
+ free() {
242
+ const gl = this._globe.gl;
243
+ this.cameraBlockTotem.unregisterAttachment(this);
244
+ if (gl) {
245
+ if (this.uniformBuffer) {
246
+ gl.deleteBuffer(this.uniformBuffer);
247
+ this.uniformBuffer = null;
248
+ }
249
+ if (this.demTexture) {
250
+ gl.deleteTexture(this.demTexture);
251
+ this.demTexture = null;
252
+ }
253
+ }
254
+ }
255
+ }
256
+ export const DemTextureManagerCache = Object.freeze({
257
+ get: (globe) => {
258
+ const result = noRegisterGlobeProgramCache.getProgram(globe, DemTextureManager);
259
+ window.demManager = result;
260
+ return result;
261
+ },
262
+ release: (globe) => {
263
+ noRegisterGlobeProgramCache.releaseProgram(globe, DemTextureManager);
264
+ }
265
+ });
@@ -1,15 +1,17 @@
1
1
  import { createProgram } from "../../../util/webglobjectbuilders";
2
2
  import { glProgramCache } from "../../programcache";
3
- import { SeaWaveUbo } from "./ubo-new";
3
+ import { ParticleUBO } from "./particle-ubo";
4
4
  /**
5
5
  * [+] ubo
6
6
  */
7
7
  const vertexShaderSource = `#version 300 es
8
8
  precision highp float;
9
- ` + SeaWaveUbo.glslCode() + `
9
+ ` + ParticleUBO.glslCode() + `
10
10
  uniform sampler2D u_vector_field;
11
+ uniform sampler2D u_color_field;
12
+ uniform sampler2D u_speed_field;
11
13
  in vec2 in_position;
12
- out vec3 base_color;
14
+ out vec4 base_color;
13
15
 
14
16
 
15
17
  vec2 read_value(const vec2 uv) {
@@ -37,7 +39,17 @@ vec2 lookup_wind(const vec2 uv) { // gerek kalmayabilir. sampler linear methodu
37
39
 
38
40
 
39
41
  void main(){
40
- vec2 direction_vector = lookup_wind(in_position);
42
+ if ( use_speed_field != 0.0 ) {
43
+ base_color = vec4(0.0);
44
+ return;
45
+ float speed = texture(u_speed_field, in_position).r;
46
+ if ( speed < min_speed_threshold || speed > max_speed_threshold ) {
47
+ base_color = vec4(0.0);
48
+ return;
49
+ }
50
+ }
51
+
52
+ vec2 direction_vector = lookup_wind(in_position);
41
53
  if (direction_vector.r == 0.0 && direction_vector.g == 0.0) return;
42
54
 
43
55
 
@@ -45,31 +57,37 @@ void main(){
45
57
  if ( 0 == gl_VertexID) { limp = -tail_wing_base_limp; }
46
58
  else if ( 1 == gl_VertexID) { limp = vec2( tail_wing_base_limp.x, -tail_wing_base_limp.y); }
47
59
  else if ( 2 == gl_VertexID) { limp = tail_wing_base_limp; }
48
- else { limp = vec2(-tail_wing_base_limp.x, tail_wing_base_limp.y); } // if ( 3 == gl_VertexID)
49
-
60
+ else { limp = vec2(-tail_wing_base_limp.x, tail_wing_base_limp.y); }
50
61
  limp = (limp * mat2(
51
62
  direction_vector.x, -direction_vector.y,
52
63
  direction_vector.y, direction_vector.x)) / draw_texture_size;
53
64
 
54
65
  vec2 pos = in_position * 2.0 - 1.0;
55
66
  gl_Position = vec4(pos + limp, 0.0, 1.0);
56
- base_color = color;
67
+
68
+ base_color = use_color_field != 0.0 ? texture(u_color_field, in_position).rgba : vec4(color, 1.0);
57
69
  }`;
58
70
  const fragmentShaderSource = `#version 300 es
59
71
  precision highp float;
60
72
  out vec4 outColor;
61
- in vec3 base_color;
73
+ in vec4 base_color;
62
74
  void main(){
63
- outColor = vec4(base_color, 1.0);
75
+ outColor = base_color;
64
76
  }`;
65
- class Logic {
77
+ export class DrawRectangleParticleProgram {
66
78
  gl;
67
79
  program;
68
80
  _vector_field_location;
81
+ _color_texture_location;
82
+ _speed_field_location;
69
83
  constructor(gl) {
70
84
  this.gl = gl;
71
- [this.program, this._vector_field_location] = this._createProgram();
72
85
  // this.decoyBuffer = new DecoyBufferManager(gl);
86
+ const { program, _vector_field_location, _color_texture_location, _speed_field_location } = this._createProgram();
87
+ this.program = program;
88
+ this._vector_field_location = _vector_field_location;
89
+ this._color_texture_location = _color_texture_location;
90
+ this._speed_field_location = _speed_field_location;
73
91
  }
74
92
  _createProgram() {
75
93
  const gl = this.gl;
@@ -77,23 +95,38 @@ class Logic {
77
95
  // ubo point
78
96
  // const ubo_location = gl.getUniformBlockIndex(program, 'UBO');
79
97
  // gl.uniformBlockBinding(program, ubo_location, UBO_BINDING_POINT);
80
- SeaWaveUbo.assignBindingPoint(gl, program);
81
- return [program, gl.getUniformLocation(program, 'u_vector_field')];
98
+ ParticleUBO.assignBindingPoint(gl, program);
99
+ return {
100
+ program,
101
+ _vector_field_location: gl.getUniformLocation(program, 'u_vector_field'),
102
+ _color_texture_location: gl.getUniformLocation(program, 'u_color_field'),
103
+ _speed_field_location: gl.getUniformLocation(program, 'u_speed_field')
104
+ };
82
105
  }
83
106
  /**
84
107
  * @param bufferManager | PingPongBufferManager
85
- * @param vectorTexture | RG32F texture R: x, G: y
108
+ * @param vectorFieldTexture | RG32F texture R: x, G: y
86
109
  * @param uboManager | WaveParticalUboManager under ubo.js
87
110
  */
88
- draw(bufferManager, vectorTexture, uboManager) {
111
+ draw(bufferManager, vectorFieldTexture, uboManager, colorFieldTexture, speedFieldTexture) {
89
112
  const { gl, program } = this;
90
113
  gl.useProgram(program);
91
114
  gl.bindVertexArray(bufferManager.getSourceVao());
92
115
  // gl.bindVertexArray(this.decoyBuffer.getSourceVao());
93
116
  uboManager.bind();
117
+ if (colorFieldTexture) {
118
+ gl.activeTexture(gl.TEXTURE1);
119
+ gl.uniform1i(this._color_texture_location, 1);
120
+ gl.bindTexture(gl.TEXTURE_2D, colorFieldTexture);
121
+ }
122
+ if (speedFieldTexture) {
123
+ gl.activeTexture(gl.TEXTURE2);
124
+ gl.uniform1i(this._speed_field_location, 2);
125
+ gl.bindTexture(gl.TEXTURE_2D, speedFieldTexture);
126
+ }
94
127
  gl.activeTexture(gl.TEXTURE0);
95
128
  gl.uniform1i(this._vector_field_location, 0);
96
- gl.bindTexture(gl.TEXTURE_2D, vectorTexture);
129
+ gl.bindTexture(gl.TEXTURE_2D, vectorFieldTexture);
97
130
  gl.drawArraysInstanced(gl.TRIANGLE_FAN, 0, 4, bufferManager.length);
98
131
  gl.drawArraysInstanced(gl.POINTS, 0, 4, bufferManager.length);
99
132
  gl.bindVertexArray(null);
@@ -106,9 +139,9 @@ class Logic {
106
139
  }
107
140
  export const drawRectangleParticlesProgramCache = Object.freeze({
108
141
  getProgram: (gl) => {
109
- return glProgramCache.getProgram(gl, Logic);
142
+ return glProgramCache.getProgram(gl, DrawRectangleParticleProgram);
110
143
  },
111
144
  releaseProgram: (gl) => {
112
- glProgramCache.releaseProgram(gl, Logic);
145
+ glProgramCache.releaseProgram(gl, DrawRectangleParticleProgram);
113
146
  }
114
147
  });
@@ -1,9 +1,7 @@
1
1
  import { UBO_BINDING_POINTS } from "./constants";
2
2
  import { UniformBlockManager } from "../../../util/gl-util/uniform-block/manager";
3
3
  const INITIAL_UBO_DATA = /*@__PURE__*/ new Float32Array([93.17, 0.2, 1.0, 7.0, 1.0, 1.0, 1.0, 0.05, 2000, 2000, 0]);
4
- //0.7297389507293701, 0.20000000298023224, 1, 7, 1, 1, 1, 0, 0.05000000074505806, 0, 2200, 656, -9999,
5
- // {float random_seed;float range;vec2 tail_wing_base_limp;vec3 color;float drop_rate;vec2 draw_texture_size;float escape_value; }
6
- export const SeaWaveUbo = /*@__PURE__*/ new UniformBlockManager("Seawave_UBO", [
4
+ export const ParticleUBO = /*@__PURE__*/ new UniformBlockManager("Seawave_UBO", [
7
5
  { name: "tail_wing_base_limp", type: "vec2", value: INITIAL_UBO_DATA.slice(2, 4) },
8
6
  { name: "draw_texture_size", type: "vec2", value: INITIAL_UBO_DATA.slice(8, 10) },
9
7
  { name: "random_seed", type: "float", value: INITIAL_UBO_DATA.slice(0, 1) },
@@ -11,15 +9,8 @@ export const SeaWaveUbo = /*@__PURE__*/ new UniformBlockManager("Seawave_UBO", [
11
9
  { name: "escape_value", type: "float", value: INITIAL_UBO_DATA.slice(10, 11) },
12
10
  { name: "drop_rate", type: "float", value: INITIAL_UBO_DATA.slice(7, 8) },
13
11
  { name: "color", type: "vec3", value: INITIAL_UBO_DATA.slice(4, 7) },
12
+ { name: "use_color_field", type: "float", value: new Float32Array([0]) },
13
+ { name: "use_speed_field", type: "float", value: new Float32Array([0]) },
14
+ { name: "min_speed_threshold", type: "float", value: new Float32Array([0]) },
15
+ { name: "max_speed_threshold", type: "float", value: new Float32Array([10000]) },
14
16
  ], UBO_BINDING_POINTS.SEAWAVE);
15
- // window add properties
16
- // const shaderUboSource = `
17
- // layout(std140) uniform UBO {
18
- // float random_seed;
19
- // float range;
20
- // vec2 tail_wing_base_limp;
21
- // vec3 color;
22
- // float drop_rate;
23
- // vec2 draw_texture_size;
24
- // float escape_value;
25
- // };`;
@@ -1,22 +1,14 @@
1
1
  import { createShader } from "../../../util/webglobjectbuilders";
2
2
  import { glProgramCache } from "../../programcache";
3
- import { SeaWaveUbo } from "./ubo-new";
4
- // program output is buffer
5
- // TODO: Mechanism for randomness
6
- // drop out mechanism
7
- // random particle position mechanism
3
+ import { ParticleUBO } from "./particle-ubo";
8
4
  const vertexShaderSource = `#version 300 es
9
- ` + SeaWaveUbo.glslCode() + `
5
+ ` + ParticleUBO.glslCode() + `
10
6
 
11
7
  uniform sampler2D vector_field;
8
+ uniform sampler2D speed_field;
12
9
  in vec2 in_position;
13
10
  out vec2 out_position;
14
11
 
15
- // float random(vec2 st){
16
- // float t = dot(st, vec2(12.9898,78.233));
17
- // return fract(sin(t) * (t+43758.5453123));
18
- // }
19
-
20
12
 
21
13
  const vec3 rand_constants = vec3(12.9898, 78.233, 4375.85453);
22
14
  float random(const vec2 co) {
@@ -47,15 +39,10 @@ vec2 lookup_wind(const vec2 uv) {
47
39
  return mix(mix(tl, tr, f.x), mix(bl, br, f.x), f.y);
48
40
  }
49
41
 
50
-
51
-
52
-
53
-
54
42
  vec2 random_position(vec2 st){
55
43
  return vec2(random(st), random(st + 1.0));
56
44
  }
57
45
 
58
-
59
46
  void main(){
60
47
  vec2 vec = lookup_wind(in_position).xy;
61
48
  if (vec.x == 0.0 && vec.y == 0.0){
@@ -67,31 +54,43 @@ void main(){
67
54
  out_position = random_position(in_position);
68
55
  return;
69
56
  }
70
- out_position = in_position + (vec / draw_texture_size) * range;
57
+ float speed_multiplier = use_speed_field != 0.0 ? texture(speed_field, in_position).r : 1.0;
58
+ out_position = in_position + (vec / draw_texture_size) * range * speed_multiplier * tail_wing_base_limp.y;
71
59
  }
72
60
  `;
73
61
  const fragmentShaderSource = `#version 300 es
74
62
  precision highp float;
75
63
  void main(){
76
64
  }`;
77
- class Logic {
65
+ export class MoveParticalProgram {
66
+ gl;
67
+ program;
68
+ _vector_field_location;
69
+ _speed_field_location;
78
70
  constructor(gl) {
79
71
  this.gl = gl;
80
- [this.program, this._vector_field_location] = this._createProgram();
72
+ [this.program, this._vector_field_location, this._speed_field_location] = this._createProgram();
81
73
  }
82
74
  /**
83
- * @param {*} bufferManager | PingPongBufferManager
84
- * @param {*} vectorTexture RG32F texture R: x, G: y
85
- * @param {*} uboManager | WaveParticalUboManager under ubo.js
75
+ * @param bufferManager - PingPongBufferManager
76
+ * @param vectorTexture - RG32F texture R: x, G: y
77
+ * @param uboManager - WaveParticalUboManager under ubo.js
86
78
  */
87
- move(bufferManager, vectorTexture, uboManager) {
79
+ move(bufferManager, vectorTexture, uboManager, speedTexture) {
88
80
  const { gl, program, _vector_field_location } = this;
81
+ if (!program)
82
+ return;
89
83
  gl.useProgram(program);
90
84
  gl.enable(gl.RASTERIZER_DISCARD);
91
85
  gl.bindVertexArray(bufferManager.getSourceVao());
92
86
  gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, bufferManager.getTargetTF());
93
87
  gl.beginTransformFeedback(gl.POINTS);
94
88
  uboManager.bind();
89
+ if (speedTexture) {
90
+ gl.activeTexture(gl.TEXTURE1);
91
+ gl.bindTexture(gl.TEXTURE_2D, speedTexture);
92
+ gl.uniform1i(this._speed_field_location, 1);
93
+ }
95
94
  gl.activeTexture(gl.TEXTURE0);
96
95
  gl.bindTexture(gl.TEXTURE_2D, vectorTexture);
97
96
  gl.uniform1i(_vector_field_location, 0);
@@ -102,6 +101,17 @@ class Logic {
102
101
  uboManager.unbind();
103
102
  gl.disable(gl.RASTERIZER_DISCARD);
104
103
  }
104
+ free() {
105
+ if (this.program) {
106
+ this.gl.deleteProgram(this.program);
107
+ this.program = null;
108
+ }
109
+ }
110
+ getInPositionLocation() {
111
+ if (!this.program)
112
+ return -1;
113
+ return this.gl.getAttribLocation(this.program, 'in_position');
114
+ }
105
115
  // -- private methods
106
116
  _createProgram() {
107
117
  const gl = this.gl;
@@ -113,27 +123,23 @@ class Logic {
113
123
  gl.transformFeedbackVaryings(program, ["out_position"], gl.SEPARATE_ATTRIBS);
114
124
  gl.linkProgram(program);
115
125
  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
116
- throw new Error(gl.getProgramParameter(program));
126
+ throw new Error(gl.getProgramInfoLog(program) || 'Program link failed');
117
127
  }
118
128
  // const ubo_location = gl.getUniformBlockIndex(program, 'UBO');
119
129
  // gl.uniformBlockBinding(program, ubo_location, UBO_BINDING_POINT);
120
- SeaWaveUbo.assignBindingPoint(gl, program, 0);
121
- return [program, gl.getUniformLocation(program, 'vector_field')];
122
- ;
123
- }
124
- free() {
125
- this.gl.deleteProgram(this.program);
126
- this.program = null;
127
- }
128
- getInPositionLocation() {
129
- return this.gl.getAttribLocation(this.program, 'in_position');
130
+ ParticleUBO.assignBindingPoint(gl, program);
131
+ return [
132
+ program,
133
+ gl.getUniformLocation(program, 'vector_field'),
134
+ gl.getUniformLocation(program, 'speed_field'),
135
+ ];
130
136
  }
131
137
  }
132
138
  export const pixelBasedMoveProgramCache = Object.freeze({
133
139
  getProgram: (gl) => {
134
- return glProgramCache.getProgram(gl, Logic);
140
+ return glProgramCache.getProgram(gl, MoveParticalProgram);
135
141
  },
136
142
  releaseProgram: (gl) => {
137
- glProgramCache.releaseProgram(gl, Logic);
143
+ glProgramCache.releaseProgram(gl, MoveParticalProgram);
138
144
  }
139
145
  });
@@ -6,12 +6,20 @@
6
6
  * update coords and draw particles programs will use this class.
7
7
  */
8
8
  export class PingPongBufferManager {
9
+ gl;
10
+ length;
11
+ _inPositionLocation;
12
+ _buffers;
13
+ _tfs;
14
+ _vaos;
15
+ _index;
9
16
  constructor(gl, particleCount, inPositionLocation = 0) {
10
17
  this.gl = gl;
11
18
  this._inPositionLocation = inPositionLocation;
12
19
  this._buffers = [gl.createBuffer(), gl.createBuffer()];
13
20
  this._tfs = this._createTransformFeedbacksAndBindBuffers();
14
21
  this._vaos = this._createVaos();
22
+ this.length = 0;
15
23
  this.setParticleCount(particleCount);
16
24
  this._index = 0;
17
25
  }
@@ -27,7 +35,10 @@ export class PingPongBufferManager {
27
35
  }
28
36
  _createTransformFeedbacksAndBindBuffers() {
29
37
  const gl = this.gl;
30
- const tfs = [gl.createTransformFeedback(), gl.createTransformFeedback()];
38
+ const tfs = [
39
+ gl.createTransformFeedback(),
40
+ gl.createTransformFeedback()
41
+ ];
31
42
  tfs.forEach((tf, idx) => {
32
43
  gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf);
33
44
  gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, this._buffers[idx]);
@@ -37,7 +48,10 @@ export class PingPongBufferManager {
37
48
  }
38
49
  _createVaos() {
39
50
  const gl = this.gl;
40
- const vaos = [gl.createVertexArray(), gl.createVertexArray()];
51
+ const vaos = [
52
+ gl.createVertexArray(),
53
+ gl.createVertexArray()
54
+ ];
41
55
  vaos.forEach((vao, idx) => {
42
56
  gl.bindVertexArray(vao);
43
57
  gl.bindBuffer(gl.ARRAY_BUFFER, this._buffers[idx]);
@@ -48,12 +62,24 @@ export class PingPongBufferManager {
48
62
  });
49
63
  return vaos;
50
64
  }
51
- getSourceVao() { return this._vaos[this._index]; }
52
- getTargetVao() { return this._vaos[1 - this._index]; }
53
- sourceBuffer() { return this._buffers[this._index]; }
54
- targetBuffer() { return this._buffers[1 - this._index]; }
55
- getTargetTF() { return this._tfs[1 - this._index]; }
56
- swap() { this._index = 1 - this._index; }
65
+ getSourceVao() {
66
+ return this._vaos[this._index];
67
+ }
68
+ getTargetVao() {
69
+ return this._vaos[1 - this._index];
70
+ }
71
+ sourceBuffer() {
72
+ return this._buffers[this._index];
73
+ }
74
+ targetBuffer() {
75
+ return this._buffers[1 - this._index];
76
+ }
77
+ getTargetTF() {
78
+ return this._tfs[1 - this._index];
79
+ }
80
+ swap() {
81
+ this._index = 1 - this._index;
82
+ }
57
83
  free() {
58
84
  this.gl.deleteBuffer(this._buffers[0]);
59
85
  this.gl.deleteBuffer(this._buffers[1]);