melonjs 10.7.1 → 10.8.0

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 (62) hide show
  1. package/dist/melonjs.js +1131 -652
  2. package/dist/melonjs.min.js +4 -4
  3. package/dist/melonjs.module.d.ts +1038 -198
  4. package/dist/melonjs.module.js +1234 -763
  5. package/package.json +7 -7
  6. package/src/camera/camera2d.js +1 -1
  7. package/src/entity/entity.js +6 -7
  8. package/src/geometries/ellipse.js +10 -11
  9. package/src/geometries/line.js +3 -3
  10. package/src/geometries/path2d.js +319 -0
  11. package/src/geometries/poly.js +11 -11
  12. package/src/geometries/rectangle.js +15 -15
  13. package/src/geometries/roundrect.js +67 -0
  14. package/src/index.js +5 -1
  15. package/src/input/pointerevent.js +1 -1
  16. package/src/lang/deprecated.js +1 -1
  17. package/src/level/tiled/TMXLayer.js +1 -1
  18. package/src/level/tiled/TMXObject.js +9 -12
  19. package/src/level/tiled/TMXTileMap.js +23 -4
  20. package/src/level/tiled/renderer/TMXHexagonalRenderer.js +1 -1
  21. package/src/level/tiled/renderer/TMXIsometricRenderer.js +1 -1
  22. package/src/level/tiled/renderer/TMXOrthogonalRenderer.js +1 -1
  23. package/src/level/tiled/renderer/TMXRenderer.js +1 -1
  24. package/src/level/tiled/renderer/TMXStaggeredRenderer.js +1 -1
  25. package/src/loader/loader.js +4 -4
  26. package/src/loader/loadingscreen.js +1 -1
  27. package/src/math/color.js +1 -1
  28. package/src/math/matrix2.js +1 -1
  29. package/src/math/matrix3.js +1 -1
  30. package/src/math/observable_vector2.js +1 -1
  31. package/src/math/observable_vector3.js +1 -1
  32. package/src/math/vector2.js +1 -1
  33. package/src/math/vector3.js +1 -1
  34. package/src/particles/emitter.js +23 -14
  35. package/src/particles/particle.js +3 -2
  36. package/src/physics/body.js +67 -51
  37. package/src/physics/bounds.js +8 -9
  38. package/src/physics/world.js +1 -1
  39. package/src/renderable/collectable.js +9 -2
  40. package/src/renderable/colorlayer.js +1 -1
  41. package/src/renderable/container.js +1 -1
  42. package/src/renderable/imagelayer.js +1 -1
  43. package/src/renderable/renderable.js +1 -1
  44. package/src/renderable/sprite.js +2 -3
  45. package/src/renderable/trigger.js +10 -4
  46. package/src/state/stage.js +1 -1
  47. package/src/state/state.js +1 -1
  48. package/src/system/device.js +10 -8
  49. package/src/system/pooling.js +156 -149
  50. package/src/text/bitmaptext.js +1 -1
  51. package/src/text/text.js +1 -1
  52. package/src/video/canvas/canvas_renderer.js +89 -34
  53. package/src/video/renderer.js +26 -14
  54. package/src/video/texture.js +1 -1
  55. package/src/video/webgl/glshader.js +29 -193
  56. package/src/video/webgl/utils/attributes.js +16 -0
  57. package/src/video/webgl/utils/precision.js +11 -0
  58. package/src/video/webgl/utils/program.js +58 -0
  59. package/src/video/webgl/utils/string.js +16 -0
  60. package/src/video/webgl/utils/uniforms.js +87 -0
  61. package/src/video/webgl/webgl_compositor.js +1 -14
  62. package/src/video/webgl/webgl_renderer.js +123 -181
@@ -189,7 +189,7 @@ class CanvasRenderer extends Renderer {
189
189
  * @param {number} height The rectangle's height.
190
190
  */
191
191
  clearRect(x, y, width, height) {
192
- this.backBufferContext2D.clearRect(x, y, width, height);
192
+ this.getContext().clearRect(x, y, width, height);
193
193
  }
194
194
 
195
195
  /**
@@ -208,7 +208,7 @@ class CanvasRenderer extends Renderer {
208
208
  * var basic = renderer.createPattern(image, "no-repeat");
209
209
  */
210
210
  createPattern(image, repeat) {
211
- return this.backBufferContext2D.createPattern(image, repeat);
211
+ return this.getContext().createPattern(image, repeat);
212
212
  }
213
213
 
214
214
  /**
@@ -234,10 +234,11 @@ class CanvasRenderer extends Renderer {
234
234
  * renderer.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
235
235
  */
236
236
  drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) {
237
- if (this.backBufferContext2D.globalAlpha < 1 / 255) {
237
+ if (this.getGlobalAlpha() < 1 / 255) {
238
238
  // Fast path: don't draw fully transparent
239
239
  return;
240
240
  }
241
+ var context = this.getContext();
241
242
 
242
243
  if (typeof sw === "undefined") {
243
244
  sw = dw = image.width;
@@ -271,7 +272,7 @@ class CanvasRenderer extends Renderer {
271
272
  // get a tinted version of this image from the texture cache
272
273
  source = this.cache.tint(image, this.currentTint.toRGB());
273
274
  }
274
- this.backBufferContext2D.drawImage(source, sx, sy, sw, sh, dx, dy, dw, dh);
275
+ context.drawImage(source, sx, sy, sw, sh, dx, dy, dw, dh);
275
276
  }
276
277
 
277
278
  /**
@@ -287,14 +288,15 @@ class CanvasRenderer extends Renderer {
287
288
  * @see CanvasRenderer#createPattern
288
289
  */
289
290
  drawPattern(pattern, x, y, width, height) {
290
- if (this.backBufferContext2D.globalAlpha < 1 / 255) {
291
+ if (this.getGlobalAlpha() < 1 / 255) {
291
292
  // Fast path: don't draw fully transparent
292
293
  return;
293
294
  }
294
- var fillStyle = this.backBufferContext2D.fillStyle;
295
- this.backBufferContext2D.fillStyle = pattern;
296
- this.backBufferContext2D.fillRect(x, y, width, height);
297
- this.backBufferContext2D.fillStyle = fillStyle;
295
+ var context = this.getContext();
296
+ var fillStyle = context.fillStyle;
297
+ context.fillStyle = pattern;
298
+ context.fillRect(x, y, width, height);
299
+ context.fillStyle = fillStyle;
298
300
  }
299
301
 
300
302
  /**
@@ -311,12 +313,12 @@ class CanvasRenderer extends Renderer {
311
313
  * @param {boolean} [fill=false] also fill the shape with the current color if true
312
314
  */
313
315
  strokeArc(x, y, radius, start, end, antiClockwise, fill = false) {
314
- var context = this.backBufferContext2D;
315
-
316
- if (context.globalAlpha < 1 / 255) {
316
+ if (this.getGlobalAlpha() < 1 / 255) {
317
317
  // Fast path: don't draw fully transparent
318
318
  return;
319
319
  }
320
+ var context = this.getContext();
321
+
320
322
  context.translate(x, y);
321
323
  context.beginPath();
322
324
  context.arc(0, 0, radius, start, end, antiClockwise || false);
@@ -352,12 +354,11 @@ class CanvasRenderer extends Renderer {
352
354
  * @param {boolean} [fill=false] also fill the shape with the current color if true
353
355
  */
354
356
  strokeEllipse(x, y, w, h, fill = false) {
355
- var context = this.backBufferContext2D;
356
-
357
- if (context.globalAlpha < 1 / 255) {
357
+ if (this.getGlobalAlpha() < 1 / 255) {
358
358
  // Fast path: don't draw fully transparent
359
359
  return;
360
360
  }
361
+ var context = this.getContext();
361
362
 
362
363
  var hw = w,
363
364
  hh = h,
@@ -408,9 +409,7 @@ class CanvasRenderer extends Renderer {
408
409
  * @param {number} endY the end y coordinate
409
410
  */
410
411
  strokeLine(startX, startY, endX, endY) {
411
- var context = this.backBufferContext2D;
412
-
413
- if (context < 1 / 255) {
412
+ if (this.getGlobalAlpha() < 1 / 255) {
414
413
  // Fast path: don't draw fully transparent
415
414
  return;
416
415
  }
@@ -444,12 +443,11 @@ class CanvasRenderer extends Renderer {
444
443
  * @param {boolean} [fill=false] also fill the shape with the current color if true
445
444
  */
446
445
  strokePolygon(poly, fill = false) {
447
- var context = this.backBufferContext2D;
448
-
449
- if (context.globalAlpha < 1 / 255) {
446
+ if (this.getGlobalAlpha() < 1 / 255) {
450
447
  // Fast path: don't draw fully transparent
451
448
  return;
452
449
  }
450
+ var context = this.getContext();
453
451
 
454
452
  this.translate(poly.pos.x, poly.pos.y);
455
453
  context.beginPath();
@@ -488,15 +486,13 @@ class CanvasRenderer extends Renderer {
488
486
  * @param {boolean} [fill=false] also fill the shape with the current color if true
489
487
  */
490
488
  strokeRect(x, y, width, height, fill = false) {
491
- if (fill === true ) {
492
- this.fillRect(x, y, width, height);
493
- } else {
494
- if (this.backBufferContext2D.globalAlpha < 1 / 255) {
495
- // Fast path: don't draw fully transparent
496
- return;
497
- }
498
- this.backBufferContext2D.strokeRect(x, y, width, height);
489
+ if (this.getGlobalAlpha() < 1 / 255) {
490
+ // Fast path: don't draw fully transparent
491
+ return;
499
492
  }
493
+ var context = this.getContext();
494
+
495
+ context[fill === true ? "fillRect" : "strokeRect"](x, y, width, height);
500
496
  }
501
497
 
502
498
  /**
@@ -510,11 +506,59 @@ class CanvasRenderer extends Renderer {
510
506
  * @param {number} height
511
507
  */
512
508
  fillRect(x, y, width, height) {
513
- if (this.backBufferContext2D.globalAlpha < 1 / 255) {
509
+ this.strokeRect(x, y, width, height, true);
510
+ }
511
+
512
+ /**
513
+ * Stroke a rounded rectangle at the specified coordinates
514
+ * @name strokeRoundRect
515
+ * @memberof CanvasRenderer.prototype
516
+ * @function
517
+ * @param {number} x
518
+ * @param {number} y
519
+ * @param {number} width
520
+ * @param {number} height
521
+ * @param {number} radius
522
+ * @param {boolean} [fill=false] also fill the shape with the current color if true
523
+ */
524
+ strokeRoundRect(x, y, width, height, radius, fill = false) {
525
+ if (this.getGlobalAlpha() < 1 / 255) {
514
526
  // Fast path: don't draw fully transparent
515
527
  return;
516
528
  }
517
- this.backBufferContext2D.fillRect(x, y, width, height);
529
+ var context = this.getContext();
530
+
531
+ context.beginPath();
532
+ if (typeof context.roundRect === "function") {
533
+ //https://developer.chrome.com/blog/canvas2d/#round-rect
534
+ context.roundRect(x, y, width, height, radius);
535
+ } else {
536
+ context.moveTo(x + radius, y);
537
+ context.lineTo(x + width - radius, y);
538
+ context.arcTo(x + width, y, x + width, y + radius, radius);
539
+ context.lineTo(x + width, y + height - radius);
540
+ context.arcTo(x + width, y + height, x + width - radius, y + height, radius);
541
+ context.lineTo(x + radius, y + height);
542
+ context.arcTo(x, y + height, x, y + height - radius, radius);
543
+ context.lineTo(x, y + radius);
544
+ context.arcTo(x, y, x + radius, y, radius);
545
+ }
546
+ context[fill === true ? "fill" : "stroke"]();
547
+ }
548
+
549
+ /**
550
+ * Draw a rounded filled rectangle at the specified coordinates
551
+ * @name fillRoundRect
552
+ * @memberof CanvasRenderer.prototype
553
+ * @function
554
+ * @param {number} x
555
+ * @param {number} y
556
+ * @param {number} width
557
+ * @param {number} height
558
+ * @param {number} radius
559
+ */
560
+ fillRoundRect(x, y, width, height, radius) {
561
+ this.strokeRoundRect(x, y, width, height, radius, true);
518
562
  }
519
563
 
520
564
 
@@ -556,7 +600,7 @@ class CanvasRenderer extends Renderer {
556
600
  */
557
601
  restore() {
558
602
  this.backBufferContext2D.restore();
559
- this.currentColor.glArray[3] = this.backBufferContext2D.globalAlpha;
603
+ this.currentColor.glArray[3] = this.getGlobalAlpha();
560
604
  this.currentScissor[0] = 0;
561
605
  this.currentScissor[1] = 0;
562
606
  this.currentScissor[2] = this.backBufferCanvas.width;
@@ -604,7 +648,7 @@ class CanvasRenderer extends Renderer {
604
648
  }
605
649
 
606
650
  /**
607
- * Set the global alpha on the canvas context
651
+ * Set the global alpha
608
652
  * @name setGlobalAlpha
609
653
  * @memberof CanvasRenderer.prototype
610
654
  * @function
@@ -614,6 +658,17 @@ class CanvasRenderer extends Renderer {
614
658
  this.backBufferContext2D.globalAlpha = this.currentColor.glArray[3] = alpha;
615
659
  }
616
660
 
661
+ /**
662
+ * Return the global alpha
663
+ * @name getGlobalAlpha
664
+ * @memberof CanvasRenderer.prototype
665
+ * @function
666
+ * @returns {number} global alpha value
667
+ */
668
+ getGlobalAlpha() {
669
+ return this.backBufferContext2D.globalAlpha;
670
+ }
671
+
617
672
  /**
618
673
  * Set the line width on the context
619
674
  * @name setLineWidth
@@ -723,7 +778,7 @@ class CanvasRenderer extends Renderer {
723
778
  * @param {Rect|Polygon|Line|Ellipse} [mask] the shape defining the mask to be applied
724
779
  */
725
780
  setMask(mask) {
726
- var context = this.backBufferContext2D;
781
+ var context = this.getContext();
727
782
  var _x = mask.pos.x, _y = mask.pos.y;
728
783
 
729
784
  context.save();
@@ -5,10 +5,12 @@ import * as event from "./../system/event.js";
5
5
  import device from "./../system/device.js";
6
6
  import { setPrefixed } from "./../utils/agent.js";
7
7
  import Rect from "./../geometries/rectangle.js";
8
+ import RoundRect from "./../geometries/roundrect.js";
8
9
  import Ellipse from "./../geometries/ellipse.js";
9
10
  import Polygon from "./../geometries/poly.js";
10
11
  import Line from "./../geometries/line.js";
11
12
  import Bounds from "./../physics/bounds.js";
13
+ import Path2D from "./../geometries/path2d.js";
12
14
 
13
15
  /**
14
16
  * @classdesc
@@ -43,12 +45,20 @@ class Renderer {
43
45
  /**
44
46
  * true if the current rendering context is valid
45
47
  * @name isContextValid
46
- * @memberof Renderer
48
+ * @memberof Renderer#
47
49
  * @default true
48
50
  * type {boolean}
49
51
  */
50
52
  this.isContextValid = true;
51
53
 
54
+ /**
55
+ * The Path2D instance used by the renderer to draw primitives
56
+ * @name path2D
57
+ * @type {Path2D}
58
+ * @memberof Renderer#
59
+ */
60
+ this.path2D = new Path2D();
61
+
52
62
  /**
53
63
  * @ignore
54
64
  */
@@ -331,11 +341,13 @@ class Renderer {
331
341
  * @name stroke
332
342
  * @memberof Renderer.prototype
333
343
  * @function
334
- * @param {Rect|Polygon|Line|Ellipse} shape a shape object to stroke
344
+ * @param {Rect|RoundRect|Polygon|Line|Ellipse} shape a shape object to stroke
335
345
  * @param {boolean} [fill=false] fill the shape with the current color if true
336
346
  */
337
347
  stroke(shape, fill) {
338
- if (shape instanceof Rect || shape instanceof Bounds) {
348
+ if (shape instanceof RoundRect) {
349
+ this.strokeRoundRect(shape.left, shape.top, shape.width, shape.height, shape.radius, fill);
350
+ } else if (shape instanceof Rect || shape instanceof Bounds) {
339
351
  this.strokeRect(shape.left, shape.top, shape.width, shape.height, fill);
340
352
  } else if (shape instanceof Line || shape instanceof Polygon) {
341
353
  this.strokePolygon(shape, fill);
@@ -350,6 +362,17 @@ class Renderer {
350
362
  }
351
363
  }
352
364
 
365
+ /**
366
+ * fill the given shape
367
+ * @name fill
368
+ * @memberof Renderer.prototype
369
+ * @function
370
+ * @param {Rect|Polygon|Line|Ellipse} shape a shape object to fill
371
+ */
372
+ fill(shape) {
373
+ this.stroke(shape, true);
374
+ }
375
+
353
376
  /**
354
377
  * tint the given image or canvas using the given color
355
378
  * @name tint
@@ -379,17 +402,6 @@ class Renderer {
379
402
  return canvas;
380
403
  }
381
404
 
382
- /**
383
- * fill the given shape
384
- * @name fill
385
- * @memberof Renderer.prototype
386
- * @function
387
- * @param {Rect|Polygon|Line|Ellipse} shape a shape object to fill
388
- */
389
- fill(shape) {
390
- this.stroke(shape, true);
391
- }
392
-
393
405
  /**
394
406
  * A mask limits rendering elements to the shape and position of the given mask object.
395
407
  * So, if the renderable is larger than the mask, only the intersecting part of the renderable will be visible.
@@ -3,7 +3,7 @@ import WebGLRenderer from "./webgl/webgl_renderer.js";
3
3
  import TextureCache from "./texture_cache.js";
4
4
  import Sprite from "./../renderable/sprite.js";
5
5
  import { renderer } from "./video.js";
6
- import * as pool from "./../system/pooling.js";
6
+ import pool from "./../system/pooling.js";
7
7
  import loader from "./../loader/loader.js";
8
8
  import { ETA } from "./../math/math.js";
9
9
 
@@ -1,198 +1,10 @@
1
1
  import * as event from "./../../system/event.js";
2
2
  import device from "./../../system/device.js";
3
-
4
- /**
5
- * @ignore
6
- */
7
- function extractUniforms(gl, shader) {
8
- var uniforms = {},
9
- uniRx = /uniform\s+(\w+)\s+(\w+)/g,
10
- uniformsData = {},
11
- descriptor = {},
12
- locations = {},
13
- match;
14
-
15
- // Detect all uniform names and types
16
- [ shader.vertex, shader.fragment ].forEach(function (shader) {
17
- while ((match = uniRx.exec(shader))) {
18
- uniformsData[match[2]] = match[1];
19
- }
20
- });
21
-
22
- // Get uniform references
23
- Object.keys(uniformsData).forEach(function (name) {
24
- var type = uniformsData[name];
25
- locations[name] = gl.getUniformLocation(shader.program, name);
26
-
27
- descriptor[name] = {
28
- "get" : (function (name) {
29
- /**
30
- * A getter for the uniform location
31
- * @ignore
32
- */
33
- return function () {
34
- return locations[name];
35
- };
36
- })(name),
37
- "set" : (function (name, type, fn) {
38
- if (type.indexOf("mat") === 0) {
39
- /**
40
- * A generic setter for uniform matrices
41
- * @ignore
42
- */
43
- return function (val) {
44
- gl[fn](locations[name], false, val);
45
- };
46
- }
47
- else {
48
- /**
49
- * A generic setter for uniform vectors
50
- * @ignore
51
- */
52
- return function (val) {
53
- var fnv = fn;
54
- if (val.length && fn.substr(-1) !== "v") {
55
- fnv += "v";
56
- }
57
- gl[fnv](locations[name], val);
58
- };
59
- }
60
- })(name, type, "uniform" + fnHash[type])
61
- };
62
- });
63
- Object.defineProperties(uniforms, descriptor);
64
-
65
- return uniforms;
66
- };
67
-
68
- /**
69
- * @ignore
70
- */
71
- function extractAttributes(gl, shader) {
72
- var attributes = {},
73
- attrRx = /attribute\s+\w+\s+(\w+)/g,
74
- match,
75
- i = 0;
76
-
77
- // Detect all attribute names
78
- while ((match = attrRx.exec(shader.vertex))) {
79
- attributes[match[1]] = i++;
80
- }
81
-
82
- return attributes;
83
- };
84
-
85
- /**
86
- * @ignore
87
- */
88
- function compileShader(gl, type, source) {
89
- var shader = gl.createShader(type);
90
- gl.shaderSource(shader, source);
91
- gl.compileShader(shader);
92
-
93
- if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
94
- throw new Error(gl.getShaderInfoLog(shader));
95
- }
96
-
97
- return shader;
98
- };
99
-
100
- /**
101
- * Compile GLSL into a shader object
102
- * @ignore
103
- */
104
- function compileProgram(gl, vertex, fragment, attributes) {
105
- var vertShader = compileShader(gl, gl.VERTEX_SHADER, vertex);
106
- var fragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragment);
107
-
108
- var program = gl.createProgram();
109
-
110
- gl.attachShader(program, vertShader);
111
- gl.attachShader(program, fragShader);
112
-
113
-
114
- // force vertex attributes to use location 0 as starting location to prevent
115
- // browser to do complicated emulation when running on desktop OpenGL (e.g. on macOS)
116
- for (var location in attributes) {
117
- gl.bindAttribLocation(program, attributes[location], location);
118
- }
119
-
120
- gl.linkProgram(program);
121
-
122
- if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
123
- var error_msg =
124
- "Error initializing Shader " + this + "\n" +
125
- "gl.VALIDATE_STATUS: " + gl.getProgramParameter(program, gl.VALIDATE_STATUS) + "\n" +
126
- "gl.getError()" + gl.getError() + "\n" +
127
- "gl.getProgramInfoLog()" + gl.getProgramInfoLog(program);
128
- // house cleaning
129
- gl.deleteProgram(program);
130
- program = null;
131
- // throw the exception
132
- throw new Error(error_msg);
133
- }
134
-
135
- gl.useProgram(program);
136
-
137
- // clean-up
138
- gl.deleteShader(vertShader);
139
- gl.deleteShader(fragShader);
140
-
141
- return program;
142
- };
143
-
144
-
145
- /**
146
- * Hash map of GLSL data types to WebGL Uniform methods
147
- * @ignore
148
- */
149
- var fnHash = {
150
- "bool" : "1i",
151
- "int" : "1i",
152
- "float" : "1f",
153
- "vec2" : "2fv",
154
- "vec3" : "3fv",
155
- "vec4" : "4fv",
156
- "bvec2" : "2iv",
157
- "bvec3" : "3iv",
158
- "bvec4" : "4iv",
159
- "ivec2" : "2iv",
160
- "ivec3" : "3iv",
161
- "ivec4" : "4iv",
162
- "mat2" : "Matrix2fv",
163
- "mat3" : "Matrix3fv",
164
- "mat4" : "Matrix4fv",
165
- "sampler2D" : "1i"
166
- };
167
-
168
- /**
169
- * set precision for the fiven shader source
170
- * won't do anything if the precision is already specified
171
- * @ignore
172
- */
173
- function setPrecision(src, precision) {
174
- if (src.substring(0, 9) !== "precision") {
175
- return "precision " + precision + " float;" + src;
176
- }
177
- return src;
178
- };
179
-
180
- /**
181
- * clean the given source from space, comments, etc...
182
- * @ignore
183
- */
184
- function minify(src) {
185
- // remove comments
186
- src = src.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, "$1");
187
- // Remove leading and trailing whitespace from lines
188
- src = src.replace(/(\\n\s+)|(\s+\\n)/g, "");
189
- // Remove line breaks
190
- src = src.replace(/(\\r|\\n)+/g, "");
191
- // Remove unnecessary whitespace
192
- src = src.replace(/\s*([;,[\](){}\\\/\-+*|^&!=<>?~%])\s*/g, "$1");
193
-
194
- return src;
195
- };
3
+ import { extractUniforms } from "./utils/uniforms.js";
4
+ import { extractAttributes } from "./utils/attributes.js";
5
+ import { compileProgram } from "./utils/program.js";
6
+ import { setPrecision } from "./utils/precision.js";
7
+ import { minify } from "./utils/string.js";
196
8
 
197
9
  /**
198
10
  * @classdesc
@@ -337,6 +149,30 @@ class GLShader {
337
149
  }
338
150
  }
339
151
 
152
+ /**
153
+ * activate the given vertex attribute for this shader
154
+ * @name setVertexAttributes
155
+ * @memberof GLShader
156
+ * @function
157
+ * @param {WebGLRenderingContext} gl the current WebGL rendering context
158
+ * @param {object[]} attributes an array of vertex attributes
159
+ * @param {number} vertexByteSize the size of a single vertex in bytes
160
+ */
161
+ setVertexAttributes(gl, attributes, vertexByteSize) {
162
+ // set the vertex attributes
163
+ for (var index = 0; index < attributes.length; ++index) {
164
+ var element = attributes[index];
165
+ var location = this.getAttribLocation(element.name);
166
+
167
+ if (location !== -1) {
168
+ gl.enableVertexAttribArray(location);
169
+ gl.vertexAttribPointer(location, element.size, element.type, element.normalized, vertexByteSize, element.offset);
170
+ } else {
171
+ gl.disableVertexAttribArray(index);
172
+ }
173
+ }
174
+ }
175
+
340
176
  /**
341
177
  * destroy this shader objects resources (program, attributes, uniforms)
342
178
  * @name destroy
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @ignore
3
+ */
4
+ export function extractAttributes(gl, shader) {
5
+ var attributes = {},
6
+ attrRx = /attribute\s+\w+\s+(\w+)/g,
7
+ match,
8
+ i = 0;
9
+
10
+ // Detect all attribute names
11
+ while ((match = attrRx.exec(shader.vertex))) {
12
+ attributes[match[1]] = i++;
13
+ }
14
+
15
+ return attributes;
16
+ };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * set precision for the fiven shader source
3
+ * won't do anything if the precision is already specified
4
+ * @ignore
5
+ */
6
+ export function setPrecision(src, precision) {
7
+ if (src.substring(0, 9) !== "precision") {
8
+ return "precision " + precision + " float;" + src;
9
+ }
10
+ return src;
11
+ };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * @ignore
3
+ */
4
+ function compileShader(gl, type, source) {
5
+ var shader = gl.createShader(type);
6
+ gl.shaderSource(shader, source);
7
+ gl.compileShader(shader);
8
+
9
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
10
+ throw new Error(gl.getShaderInfoLog(shader));
11
+ }
12
+
13
+ return shader;
14
+ };
15
+
16
+ /**
17
+ * Compile GLSL into a shader object
18
+ * @ignore
19
+ */
20
+ export function compileProgram(gl, vertex, fragment, attributes) {
21
+ var vertShader = compileShader(gl, gl.VERTEX_SHADER, vertex);
22
+ var fragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragment);
23
+
24
+ var program = gl.createProgram();
25
+
26
+ gl.attachShader(program, vertShader);
27
+ gl.attachShader(program, fragShader);
28
+
29
+
30
+ // force vertex attributes to use location 0 as starting location to prevent
31
+ // browser to do complicated emulation when running on desktop OpenGL (e.g. on macOS)
32
+ for (var location in attributes) {
33
+ gl.bindAttribLocation(program, attributes[location], location);
34
+ }
35
+
36
+ gl.linkProgram(program);
37
+
38
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
39
+ var error_msg =
40
+ "Error initializing Shader " + this + "\n" +
41
+ "gl.VALIDATE_STATUS: " + gl.getProgramParameter(program, gl.VALIDATE_STATUS) + "\n" +
42
+ "gl.getError()" + gl.getError() + "\n" +
43
+ "gl.getProgramInfoLog()" + gl.getProgramInfoLog(program);
44
+ // house cleaning
45
+ gl.deleteProgram(program);
46
+ program = null;
47
+ // throw the exception
48
+ throw new Error(error_msg);
49
+ }
50
+
51
+ gl.useProgram(program);
52
+
53
+ // clean-up
54
+ gl.deleteShader(vertShader);
55
+ gl.deleteShader(fragShader);
56
+
57
+ return program;
58
+ };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * clean the given source from space, comments, etc...
3
+ * @ignore
4
+ */
5
+ export function minify(src) {
6
+ // remove comments
7
+ src = src.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, "$1");
8
+ // Remove leading and trailing whitespace from lines
9
+ src = src.replace(/(\\n\s+)|(\s+\\n)/g, "");
10
+ // Remove line breaks
11
+ src = src.replace(/(\\r|\\n)+/g, "");
12
+ // Remove unnecessary whitespace
13
+ src = src.replace(/\s*([;,[\](){}\\\/\-+*|^&!=<>?~%])\s*/g, "$1");
14
+
15
+ return src;
16
+ };