@pirireis/webglobeplugins 0.9.3 → 0.9.4

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.
@@ -68,7 +68,7 @@ const attributeLoader = (
68
68
  * @param {number} offset
69
69
  * @returns {BufferAndReadInfo}
70
70
  */
71
- const createBufferAndReadInfo = (buffer: WebGLBuffer, stride: number = 0, offset: number = 0): BufferAndReadInfo => {
71
+ const createBufferAndReadInfo = (buffer: WebGLBuffer, stride: number = 0, offset: number = 0): BufferAndReadInfo | null => {
72
72
  if (buffer == null) return null;
73
73
  return { buffer, stride, offset };
74
74
  }
@@ -77,7 +77,7 @@ const createBufferAndReadInfo = (buffer: WebGLBuffer, stride: number = 0, offset
77
77
 
78
78
  const constantFunction = (gl: WebGL2RenderingContext, index: number, size: number, escapeValues: Array<number>) => {
79
79
  const func = `vertexAttrib${size}f`;
80
- console.log(`Using constant function ${func}`, gl[func], escapeValues);
80
+ // @ts-ignore
81
81
  gl[func](index, ...escapeValues);
82
82
  }
83
83
 
@@ -0,0 +1,66 @@
1
+ import './types'
2
+
3
+ /**
4
+ * Represents the range of vertices or instances to draw.
5
+ */
6
+ interface DrawRange {
7
+ first?: number;
8
+ count: number;
9
+ }
10
+
11
+ /**
12
+ * Parameters for drawing with optional element buffer and draw mode.
13
+ */
14
+ interface DrawRangeIndexParams {
15
+ drawRange: DrawRange;
16
+ elementBuffer?: WebGLBuffer | null;
17
+ elementBufferIndexType?: GLenum;
18
+ drawMode?: GLenum | null;
19
+ }
20
+
21
+ /**
22
+ * Draws instanced geometry using WebGL2.
23
+ */
24
+ const drawInstanced = (
25
+ gl: WebGL2RenderingContext,
26
+ mode: GLenum,
27
+ drawOptions: DrawRangeIndexParams,
28
+ vertexCount: number
29
+ ): void => {
30
+ const { drawRange, elementBufferIndexType = gl.UNSIGNED_INT } = drawOptions;
31
+ const { first = 0, count: instanceCount = 1 } = drawRange;
32
+ if (first > 0 || drawOptions.elementBuffer) {
33
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, drawOptions.elementBuffer ?? null);
34
+ gl.drawElementsInstanced(mode, vertexCount, elementBufferIndexType, first, instanceCount);
35
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
36
+ } else {
37
+ gl.drawArraysInstanced(mode, first, vertexCount, instanceCount);
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Draws geometry using WebGL2.
43
+ */
44
+ const drawArrays = (
45
+ gl: WebGL2RenderingContext,
46
+ defaultMode: GLenum,
47
+ drawOptions: DrawRangeIndexParams
48
+ ): void => {
49
+ const {
50
+ drawRange,
51
+ elementBuffer,
52
+ elementBufferIndexType = gl.UNSIGNED_INT,
53
+ drawMode = null
54
+ } = drawOptions;
55
+ const { first = 0, count } = drawRange;
56
+ const mode = drawMode ?? defaultMode;
57
+ if (elementBuffer) {
58
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
59
+ gl.drawElements(mode, count, elementBufferIndexType, first);
60
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
61
+ } else {
62
+ gl.drawArrays(mode, first, count);
63
+ }
64
+ }
65
+
66
+ export { drawArrays, drawInstanced }
@@ -89,15 +89,16 @@ class UniformBlockManager {
89
89
  }
90
90
 
91
91
 
92
- createUBO(gl: WebGL2RenderingContext, bufferWriteType = "STATIC_DRAW"): UBOHandler {
92
+ createUBO(gl: WebGL2RenderingContext, bufferWriteType: string = "STATIC_DRAW"): UBOHandler {
93
93
  const ubo = gl.createBuffer();
94
94
  gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
95
+ // @ts-ignore
95
96
  gl.bufferData(gl.UNIFORM_BUFFER, this.size, gl[bufferWriteType]);
96
97
  gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, ubo);
97
98
 
98
99
  for (const member of this.blockMembers) {
99
100
  const { name, type, value = null } = member;;
100
- const offset = this.offsetMap.get(name);
101
+ const offset = this.offsetMap.get(name) as number;
101
102
  const data = (value === null) ? new typeArrayConstructors[type](typeSizes[type] / 4).fill(NaN) : value;
102
103
  gl.bufferSubData(gl.UNIFORM_BUFFER, offset, data);
103
104
  }
@@ -120,9 +121,8 @@ class UniformBlockManager {
120
121
  if (offset === undefined) {
121
122
  throw new Error(`Uniform block member ${name} not found in offset map.`);
122
123
  }
123
- console.log("Updating UBO member:", name, "with value:", value, "at offset:", offset);
124
+ // @ts-ignore
124
125
  const type = this.blockMembers.find(member => member.name === name).type;
125
- console.log("Type of member:", name, "is", type);
126
126
  let data: Float32Array | Int32Array | ArrayBuffer | DataView;
127
127
  if (Array.isArray(value)) {
128
128
  data = new typeArrayConstructors[type](value);
@@ -176,7 +176,7 @@ class UniformBlockManager {
176
176
 
177
177
  // __create_LayoutSTD140_OffsetMap() should be called before this
178
178
  __calculateSize() {
179
- const lastOffset = Array.from(this.offsetMap.values()).pop();
179
+ const lastOffset = Array.from(this.offsetMap.values()).pop() as number || 0;
180
180
  const lastItemAlignment = typeAlignments[this.blockMembers[this.blockMembers.length - 1].type];
181
181
  return lastOffset + lastItemAlignment;
182
182
  }
@@ -0,0 +1,456 @@
1
+ /**
2
+ * Creates and compiles a WebGL shader.
3
+ * @param gl The WebGL2RenderingContext.
4
+ * @param type The type of shader (e.g., gl.VERTEX_SHADER or gl.FRAGMENT_SHADER).
5
+ * @param source The GLSL source code for the shader.
6
+ * @returns The compiled WebGLShader.
7
+ * @throws An error if shader compilation fails.
8
+ */
9
+ export function createShader(gl: WebGL2RenderingContext, type: GLenum, source: string): WebGLShader {
10
+ const shader = gl.createShader(type);
11
+ if (!shader) {
12
+ throw new Error("Failed to create WebGLShader.");
13
+ }
14
+
15
+ gl.shaderSource(shader, source);
16
+ gl.compileShader(shader);
17
+
18
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
19
+ const errorLog = gl.getShaderInfoLog(shader);
20
+ const shaderType = type === gl.VERTEX_SHADER ? 'VERTEX_SHADER' : 'FRAGMENT_SHADER';
21
+ const sourceWithLineNumbers = source.split('\n').map((line, i) => `${i + 1}: ${line}`).join('\n');
22
+ gl.deleteShader(shader); // Clean up the failed shader
23
+ throw new Error(`Error compiling ${shaderType}:\n${errorLog}\nSource:\n${sourceWithLineNumbers}`);
24
+ }
25
+
26
+ return shader;
27
+ }
28
+
29
+
30
+ /**
31
+ * Creates, compiles, and links a WebGL program from vertex and fragment shader sources.
32
+ * Note: This function logs errors to the console and returns `undefined` on failure.
33
+ * Consider using `createProgramWrapper` for more robust error handling.
34
+ * @param gl The WebGL2RenderingContext.
35
+ * @param vertexSource The GLSL source code for the vertex shader.
36
+ * @param fragmentSource The GLSL source code for the fragment shader.
37
+ * @returns The linked WebGLProgram, or `undefined` if compilation or linking fails.
38
+ */
39
+ export function createProgram(gl: WebGL2RenderingContext, vertexSource: string, fragmentSource: string): WebGLProgram | undefined {
40
+ const program = gl.createProgram();
41
+ if (!program) {
42
+ console.error("Failed to create WebGLProgram.");
43
+ return undefined;
44
+ }
45
+
46
+ let vertexShader: WebGLShader | undefined;
47
+ let fragmentShader: WebGLShader | undefined;
48
+
49
+ try {
50
+ vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSource);
51
+ fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
52
+ } catch (e: any) { // Catching errors from createShader
53
+ console.error(e.message);
54
+ gl.deleteProgram(program); // Clean up the program if shaders failed
55
+ return undefined;
56
+ }
57
+
58
+ gl.attachShader(program, vertexShader);
59
+ gl.attachShader(program, fragmentShader);
60
+ gl.linkProgram(program);
61
+
62
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
63
+ console.error("Failed to link WebGL program:", gl.getProgramInfoLog(program));
64
+ gl.deleteProgram(program);
65
+ gl.deleteShader(vertexShader);
66
+ gl.deleteShader(fragmentShader);
67
+ return undefined;
68
+ }
69
+
70
+ // Detach and delete shaders after linking to free up resources
71
+ gl.detachShader(program, vertexShader);
72
+ gl.detachShader(program, fragmentShader);
73
+ gl.deleteShader(vertexShader);
74
+ gl.deleteShader(fragmentShader);
75
+
76
+ return program;
77
+ }
78
+
79
+
80
+ /**
81
+ * Interface for the program wrapper object returned by `createProgramWrapper`.
82
+ * It includes the `program` itself, and dynamically added properties for attribute and uniform locations.
83
+ */
84
+ export interface ProgramWrapper extends WebGLProgram {
85
+ program: WebGLProgram;
86
+ [key: string]: WebGLProgram | number | WebGLUniformLocation | null; // Allow dynamic properties for attributes/uniforms
87
+ }
88
+
89
+ /**
90
+ * Creates, links a WebGL program, and wraps it with convenience properties
91
+ * for attribute and uniform locations.
92
+ * @param gl The WebGL2RenderingContext.
93
+ * @param vertexSource The GLSL source code for the vertex shader.
94
+ * @param fragmentSource The GLSL source code for the fragment shader.
95
+ * @returns A ProgramWrapper object containing the WebGLProgram and its active attribute/uniform locations.
96
+ * @throws An error if shader compilation or program linking fails.
97
+ */
98
+ export function createProgramWrapper(gl: WebGL2RenderingContext, vertexSource: string, fragmentSource: string): ProgramWrapper {
99
+ const program = gl.createProgram();
100
+ if (!program) {
101
+ throw new Error("Failed to create WebGLProgram.");
102
+ }
103
+
104
+ const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSource);
105
+ const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
106
+
107
+ gl.attachShader(program, vertexShader);
108
+ gl.attachShader(program, fragmentShader);
109
+
110
+ gl.linkProgram(program);
111
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
112
+ const errorLog = gl.getProgramInfoLog(program);
113
+ gl.deleteProgram(program);
114
+ gl.deleteShader(vertexShader);
115
+ gl.deleteShader(fragmentShader);
116
+ throw new Error(`Error linking program:\n${errorLog}`);
117
+ }
118
+
119
+ // Detach and delete shaders after linking
120
+ gl.detachShader(program, vertexShader);
121
+ gl.detachShader(program, fragmentShader);
122
+ gl.deleteShader(vertexShader);
123
+ gl.deleteShader(fragmentShader);
124
+
125
+ // Using an object literal for dynamic properties
126
+ const wrapper: ProgramWrapper = { program: program };
127
+
128
+ const numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
129
+ for (let i = 0; i < numAttributes; i++) {
130
+ const attribute = gl.getActiveAttrib(program, i);
131
+ if (attribute) {
132
+ wrapper[attribute.name] = gl.getAttribLocation(program, attribute.name);
133
+ }
134
+ }
135
+
136
+ const numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
137
+ for (let i = 0; i < numUniforms; i++) {
138
+ const uniform = gl.getActiveUniform(program, i);
139
+ if (uniform) {
140
+ wrapper[uniform.name] = gl.getUniformLocation(program, uniform.name);
141
+ }
142
+ }
143
+
144
+ return wrapper;
145
+ }
146
+
147
+
148
+ /**
149
+ * Creates and configures a WebGL texture.
150
+ * @param gl The WebGL2RenderingContext.
151
+ * @param filter The texture filter (e.g., gl.LINEAR, gl.NEAREST).
152
+ * @param data The image data (e.g., ImageData, HTMLImageElement, HTMLCanvasElement, HTMLVideoElement, ImageBitmap, or Uint8Array).
153
+ * @param width The width of the texture (required if data is Uint8Array).
154
+ * @param height The height of the texture (required if data is Uint8Array).
155
+ * @returns The created WebGLTexture.
156
+ * @throws An error if texture creation fails.
157
+ */
158
+ export function createTexture(
159
+ gl: WebGL2RenderingContext,
160
+ filter: GLenum,
161
+ data: TexImageSource | Uint8Array | null | any,
162
+ width?: number,
163
+ height?: number
164
+ ): WebGLTexture {
165
+ const texture = gl.createTexture();
166
+ if (!texture) {
167
+ throw new Error("Failed to create WebGLTexture.");
168
+ }
169
+ gl.bindTexture(gl.TEXTURE_2D, texture);
170
+
171
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
172
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
173
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
174
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
175
+
176
+ if (data instanceof Uint8Array) {
177
+ if (width === undefined || height === undefined) {
178
+ throw new Error("Width and height must be provided when data is Uint8Array.");
179
+ }
180
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
181
+ } else {
182
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, data);
183
+ }
184
+ gl.bindTexture(gl.TEXTURE_2D, null);
185
+ return texture;
186
+ }
187
+
188
+
189
+ /**
190
+ * Binds a WebGL texture to a specific texture unit.
191
+ * @param gl The WebGL2RenderingContext.
192
+ * @param texture The WebGLTexture to bind.
193
+ * @param unit The texture unit to activate (e.g., 0 for TEXTURE0, 1 for TEXTURE1).
194
+ */
195
+ export function bindTexture(gl: WebGL2RenderingContext, texture: WebGLTexture | null, unit: number): void {
196
+ gl.activeTexture(gl.TEXTURE0 + unit);
197
+ gl.bindTexture(gl.TEXTURE_2D, texture);
198
+ }
199
+
200
+
201
+ /**
202
+ * Creates a WebGL buffer and uploads data to it.
203
+ * @param gl The WebGL2RenderingContext.
204
+ * @param data The data to upload to the buffer (e.g., Float32Array, Uint16Array).
205
+ * @returns The created WebGLBuffer.
206
+ * @throws An error if buffer creation fails.
207
+ */
208
+ export function createBuffer(gl: WebGL2RenderingContext, data: BufferSource): WebGLBuffer {
209
+ const buffer = gl.createBuffer();
210
+ if (!buffer) {
211
+ throw new Error("Failed to create WebGLBuffer.");
212
+ }
213
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
214
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
215
+ return buffer;
216
+ }
217
+
218
+
219
+
220
+ /**
221
+ * Binds a buffer to a specific attribute location and configures the vertex attribute pointer.
222
+ * @param gl The WebGL2RenderingContext.
223
+ * @param buffer The WebGLBuffer to bind.
224
+ * @param attribute The attribute location (e.g., from `gl.getAttribLocation`).
225
+ * @param numComponents The number of components per vertex attribute (e.g., 2 for vec2, 3 for vec3).
226
+ */
227
+ export function bindAttribute(gl: WebGL2RenderingContext, buffer: WebGLBuffer | null, attribute: GLint, numComponents: GLint): void {
228
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
229
+ gl.enableVertexAttribArray(attribute);
230
+ gl.vertexAttribPointer(attribute, numComponents, gl.FLOAT, false, 0, 0);
231
+ }
232
+
233
+
234
+ /**
235
+ * Binds a WebGL framebuffer and optionally attaches a texture to it.
236
+ * @param gl The WebGL2RenderingContext.
237
+ * @param framebuffer The WebGLFramebuffer to bind.
238
+ * @param texture The WebGLTexture to attach to the framebuffer's COLOR_ATTACHMENT0, or `null` to unbind.
239
+ */
240
+ export function bindFramebuffer(gl: WebGL2RenderingContext, framebuffer: WebGLFramebuffer | null, texture: WebGLTexture | null): void {
241
+ gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
242
+ if (texture) {
243
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
244
+ }
245
+ }
246
+
247
+
248
+ /**
249
+ * Decodes a base64 encoded string into a Uint8Array.
250
+ * @param data The base64 encoded string.
251
+ * @returns A Uint8Array containing the decoded bytes.
252
+ */
253
+ export function decodeBase64(data: string): Uint8Array {
254
+ const binary_string = atob(data);
255
+ const len = binary_string.length;
256
+ const bytes = new Uint8Array(len);
257
+ for (let i = 0; i < len; i++) {
258
+ bytes[i] = binary_string.charCodeAt(i);
259
+ }
260
+ return bytes;
261
+ }
262
+
263
+
264
+ /**
265
+ * Creates an HTMLImageElement from a base64 encoded image string.
266
+ * @param encodedData The base64 encoded image data (e.g., "iVBORw0KGgo...").
267
+ * @returns An HTMLImageElement with the image data loaded.
268
+ */
269
+ export function createImageFromBase64(encodedData: string): HTMLImageElement {
270
+ const bytes = decodeBase64(encodedData);
271
+ const blob = new Blob([bytes.buffer], { type: "image/png" });
272
+ const urlCreator = window.URL || window.webkitURL;
273
+ const imageUrl = urlCreator.createObjectURL(blob);
274
+ const image = new Image();
275
+ image.src = imageUrl;
276
+ // Revoke the object URL after the image has loaded to free up memory
277
+ image.onload = () => urlCreator.revokeObjectURL(imageUrl);
278
+ return image;
279
+ }
280
+
281
+
282
+ /**
283
+ * Creates a 1x256 pixel color ramp (gradient) as a Uint8Array.
284
+ * @param colors An object where keys are stop positions (0.0-1.0) and values are CSS color strings (e.g., { "0.0": "#RRGGBB", "0.5": "rgba(R,G,B,A)" }).
285
+ * @returns A Uint8Array representing the RGBA pixel data of the 1x256 color ramp.
286
+ */
287
+ export function getColorRamp(colors: { [stop: string]: string }): Uint8Array {
288
+ const canvas = document.createElement('canvas');
289
+ const ctx = canvas.getContext('2d');
290
+
291
+ if (!ctx) {
292
+ throw new Error("Failed to get 2D rendering context for canvas.");
293
+ }
294
+
295
+ canvas.width = 256;
296
+ canvas.height = 1;
297
+
298
+ const gradient = ctx.createLinearGradient(0, 0, 256, 0);
299
+
300
+ for (const stop in colors) {
301
+ // Ensure the stop is a valid number, although `addColorStop` can parse strings,
302
+ // explicit conversion is safer for object keys if they come from arbitrary sources.
303
+ const stopValue = parseFloat(stop);
304
+ if (isNaN(stopValue)) {
305
+ console.warn(`Invalid stop value for color ramp: ${stop}. Skipping.`);
306
+ continue;
307
+ }
308
+ gradient.addColorStop(stopValue, colors[stop]);
309
+ }
310
+
311
+ ctx.fillStyle = gradient;
312
+ ctx.fillRect(0, 0, 256, 1);
313
+
314
+ return new Uint8Array(ctx.getImageData(0, 0, 256, 1).data);
315
+ }
316
+
317
+
318
+ /**
319
+ * Creates a 1x256 pixel discrete color ramp as a Uint8Array.
320
+ * This ramp features sharp transitions between colors at specified thresholds.
321
+ * @param values An array of CSS color strings.
322
+ * @param thresholds An array of stop positions (0.0-1.0) for the colors.
323
+ * @returns A Uint8Array representing the RGBA pixel data of the 1x256 discrete color ramp.
324
+ */
325
+ export function getColorRampDiscrate(values: string[], thresholds: number[]): Uint8Array {
326
+ const canvas = document.createElement('canvas');
327
+ const ctx = canvas.getContext('2d');
328
+
329
+ if (!ctx) {
330
+ throw new Error("Failed to get 2D rendering context for canvas.");
331
+ }
332
+
333
+ canvas.width = 256;
334
+ canvas.height = 1;
335
+
336
+ const gap = 1.0 / 256; // Represents one pixel width in normalized coordinates
337
+
338
+ const gradient = ctx.createLinearGradient(0, 0, 256, 0);
339
+
340
+ for (let i = 0; i < thresholds.length - 1; i++) {
341
+ gradient.addColorStop(thresholds[i], values[i]);
342
+ // Create a sharp transition by setting the next stop just before the next threshold
343
+ gradient.addColorStop(Math.max(0, thresholds[i + 1] - gap), values[i]);
344
+ }
345
+ // Add the final color for the last segment
346
+ gradient.addColorStop(thresholds[thresholds.length - 1], values[values.length - 1]);
347
+
348
+ ctx.fillStyle = gradient;
349
+ ctx.fillRect(0, 0, 256, 1);
350
+
351
+ return new Uint8Array(ctx.getImageData(0, 0, 256, 1).data);
352
+ }
353
+
354
+
355
+ /**
356
+ * Creates a 1x256 pixel interpolated color ramp (smooth gradient) as a Uint8Array.
357
+ * @param values An array of CSS color strings.
358
+ * @param thresholds An array of stop positions (0.0-1.0) for the colors.
359
+ * @returns A Uint8Array representing the RGBA pixel data of the 1x256 interpolated color ramp.
360
+ */
361
+ export function getColorRampInterpolated(values: string[], thresholds: number[]): Uint8Array {
362
+ const canvas = document.createElement('canvas');
363
+ const ctx = canvas.getContext('2d');
364
+
365
+ if (!ctx) {
366
+ throw new Error("Failed to get 2D rendering context for canvas.");
367
+ }
368
+
369
+ canvas.width = 256;
370
+ canvas.height = 1;
371
+
372
+ const gradient = ctx.createLinearGradient(0, 0, 256, 0);
373
+
374
+ for (let i = 0; i < thresholds.length; i++) {
375
+ gradient.addColorStop(thresholds[i], values[i]);
376
+ }
377
+
378
+ ctx.fillStyle = gradient;
379
+ ctx.fillRect(0, 0, 256, 1);
380
+
381
+ return new Uint8Array(ctx.getImageData(0, 0, 256, 1).data);
382
+ }
383
+
384
+
385
+ /**
386
+ * Creates a 1x256 pixel color ramp based on the specified mode (discrete or interpolated).
387
+ * @param values An array of color hex values (e.g., ["#ff0000", "#00ff00", "#0000ff"]).
388
+ * @param thresholds An array of thresholds (0.0-1.0) for the colors.
389
+ * @param mode The ramp mode: "discrete" for sharp transitions, "interpolated" for smooth transitions (default).
390
+ * @returns A Uint8Array representing the RGBA pixel data of the 1x256 color ramp.
391
+ * @throws An error if an invalid mode is provided.
392
+ */
393
+ export function getColorRampModed(values: string[], thresholds: number[], mode: "discrete" | "interpolated" = "interpolated"): Uint8Array {
394
+ if (mode === "discrete") {
395
+ return getColorRampDiscrate(values, thresholds);
396
+ } else if (mode === "interpolated") {
397
+ return getColorRampInterpolated(values, thresholds);
398
+ } else {
399
+ throw new Error("mode is not valid. Expected 'discrete' or 'interpolated'.");
400
+ }
401
+ }
402
+
403
+
404
+
405
+ /**
406
+ * Returns a default interpolated color ramp commonly used for visualizations.
407
+ * @returns A Uint8Array representing the RGBA pixel data of the default 1x256 color ramp.
408
+ */
409
+ export function defaultColorRamp(): Uint8Array {
410
+ const defaultRampColors: { [stop: string]: string } = {
411
+ "0.0": '#5e4fa2',
412
+ "0.15": '#3288bd',
413
+ "0.20": '#66c2a5',
414
+ "0.25": '#66c2a5',
415
+ "0.3": '#abdda4',
416
+ "0.4": '#e6f598',
417
+ "0.5": '#fee08b',
418
+ "0.6": '#fdae61',
419
+ "0.7": '#f46d43',
420
+ "1.0": '#ff1e13'
421
+ };
422
+ return getColorRamp(defaultRampColors);
423
+ }
424
+
425
+
426
+
427
+ /**
428
+ * A method decorator that reloads the current WebGL program after the decorated method executes.
429
+ * This is useful for ensuring the correct program is active after a method might change it.
430
+ * @returns A method decorator function.
431
+ */
432
+ export function reloadCurrentGLProgram() {
433
+ return function (target: any, key: string, descriptor: PropertyDescriptor) {
434
+ const originalMethod = descriptor.value;
435
+
436
+ // Ensure the target has a 'gl' property of type WebGL2RenderingContext
437
+ if (!('gl' in target) || !(target.gl instanceof WebGL2RenderingContext)) {
438
+ console.warn(`Decorator 'reloadCurrentGLProgram' applied to a method where 'this.gl' is not a WebGL2RenderingContext. This may not function as expected.`);
439
+ // Optionally, throw an error here if strictness is desired
440
+ }
441
+
442
+ descriptor.value = function (this: { gl: WebGL2RenderingContext } & any, ...args: any[]) {
443
+ const gl = this.gl;
444
+ if (!gl) {
445
+ console.error("reloadCurrentGLProgram decorator: 'gl' context not found on 'this'.");
446
+ return originalMethod.apply(this, args);
447
+ }
448
+
449
+ const currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
450
+ originalMethod.apply(this, args);
451
+ gl.useProgram(currentProgram);
452
+ };
453
+
454
+ return descriptor;
455
+ };
456
+ }
@@ -1,59 +0,0 @@
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
- }
@@ -1,46 +0,0 @@
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, elementBufferIndexType = 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, elementBufferIndexType, 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, elementBufferIndexType = 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, elementBufferIndexType, first);
40
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
41
- } else {
42
- gl.drawArrays(mode, first, count);
43
- }
44
- }
45
-
46
- export { drawArrays, drawInstanced }
File without changes