littlejsengine 1.24.3 → 1.25.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.
@@ -46,11 +46,12 @@ let glAntialias = true;
46
46
 
47
47
  // WebGL internal variables not exposed to documentation
48
48
  let glMipmappedTextures = new WeakSet, glMipmapsUntilTarget = new WeakSet, glMipmapsStale = new Set, glPremultipliedTextures = new WeakSet, glShaderPremultiplied, glEnableBeforeLoss = true, glShader, glPolyShader, glPolyMode, glAdditive, glBatchAdditive, glActiveTexture, glArrayBuffer, glGeometryBuffer, glPositionData, glColorData, glBatchCount, glTextureInfos = new Set, glInstancedVAO, glPolyVAO, glFramebuffer, glRenderTarget, glShaderObjects = [], glCustomShader, glBatchShader, glProgramCustom, glTransform, glRenderTargetSaved, glUniformLocations = new WeakMap, glCanBeEnabled = true;
49
+ let glFailedPrograms = new WeakSet; // programs that did not build in a release build, which nothing draws with
49
50
  // ANDed onto every packed color as a draw is queued; the light system's shadow pass sets 0xff000000
50
51
  // to draw everything black with its alpha kept (rgbaInt packs alpha in the top byte)
51
52
  let glColorMask = -1;
52
53
  // ORed onto the additive color of every quad and onto every poly point's color as a draw is queued; the light system's
53
- // emissive pass sets a grey with the mask at 0xff000000, so a draw comes out that grey in its own shape
54
+ // emissive pass sets a gray with the mask at 0xff000000, so a draw comes out that gray in its own shape
54
55
  let glColorAdditive = 0;
55
56
  // a texture drawn into with the canvas's own transform and its size, the light system's lightmap while its pass
56
57
  // runs: a target set and ended inside it, like a tile layer redrawn in a renderLight, goes back to it, not the canvas
@@ -218,6 +219,14 @@ function glInit(rootElement)
218
219
  '}' // end of shader
219
220
  );
220
221
 
222
+ // a device that can not build the engine's own programs draws with Canvas2D, as after a lost context
223
+ if (glFailedPrograms.has(glShader) || glFailedPrograms.has(glPolyShader))
224
+ {
225
+ console.error('LittleJS: WebGL can not draw on this device, using Canvas2D');
226
+ glEnable = glCanBeEnabled = false;
227
+ glCanvas.style.display = 'none';
228
+ }
229
+
221
230
  // init buffers
222
231
  const glInstanceData = new ArrayBuffer(gl_ARRAY_BUFFER_SIZE);
223
232
  glPositionData = new Float32Array(glInstanceData);
@@ -464,13 +473,23 @@ function glCreateProgram(vsSource, fsSource)
464
473
 
465
474
  // build the program
466
475
  const program = glContext.createProgram();
467
- glContext.attachShader(program, glCompileShader(vsSource, glContext.VERTEX_SHADER));
468
- glContext.attachShader(program, glCompileShader(fsSource, glContext.FRAGMENT_SHADER));
476
+ const vertexShader = glCompileShader(vsSource, glContext.VERTEX_SHADER);
477
+ const fragmentShader = glCompileShader(fsSource, glContext.FRAGMENT_SHADER);
478
+ glContext.attachShader(program, vertexShader);
479
+ glContext.attachShader(program, fragmentShader);
469
480
  glContext.linkProgram(program);
470
481
 
471
- // check for errors
472
- if (debug && !glContext.getProgramParameter(program, glContext.LINK_STATUS))
473
- throw glContext.getProgramInfoLog(program);
482
+ // check for errors in every build, as a driver may refuse what another takes: a debug build throws, a release
483
+ // one says why once and marks the program, which the engine's draws then do without
484
+ if (!glContext.getProgramParameter(program, glContext.LINK_STATUS))
485
+ {
486
+ const log = glContext.getProgramInfoLog(program) + '\n' +
487
+ glContext.getShaderInfoLog(vertexShader) + glContext.getShaderInfoLog(fragmentShader);
488
+ if (debug)
489
+ throw log;
490
+ console.error('LittleJS: a shader failed to build\n' + log);
491
+ glFailedPrograms.add(program);
492
+ }
474
493
  return program;
475
494
  }
476
495
 
@@ -486,7 +505,7 @@ function glUniformLocation(program, name)
486
505
  // color, then the sprite's color and additive color apply as the engine's own fragment shader does
487
506
  function glShaderProgram(shader)
488
507
  {
489
- return shader.program ||= glCreateProgram(gl_VERTEX_SOURCE,
508
+ const program = shader.program ||= glCreateProgram(gl_VERTEX_SOURCE,
490
509
  '#version 300 es\n' +
491
510
  'precision highp float;' +
492
511
  'uniform sampler2D iChannel0;' + // the texture
@@ -497,6 +516,7 @@ function glShaderProgram(shader)
497
516
  '#define localUV l\n' +
498
517
  shader.fragmentCode + '\n' +
499
518
  'void main(){vec4 t;mainImage(t,v);' + gl_FRAGMENT_TINT_SOURCE + '}');
519
+ return glFailedPrograms.has(program) ? glShader : program;
500
520
  }
501
521
 
502
522
  /** Create WebGL texture from an image and init the texture settings
@@ -673,6 +693,8 @@ function glFlush()
673
693
  const height = glRenderTarget ? mainCanvasSize.y : glCanvas.height;
674
694
  glContext.uniform3f(uniform('iResolution'), width, height, 1);
675
695
  glContext.uniform1i(uniform('premultipliedTexture'), +premultiplied);
696
+ if (program === glShader)
697
+ glShaderPremultiplied = premultiplied; // a Shader that did not build draws with the engine's
676
698
  }
677
699
  }
678
700
  if (!glPolyMode && !glBatchShader && glShaderPremultiplied !== premultiplied)
@@ -730,8 +752,8 @@ function glSetAntialias(antialias=true)
730
752
  * @param {number} [uv0Y]
731
753
  * @param {number} [uv1X]
732
754
  * @param {number} [uv1Y]
733
- * @param {number} [rgba=-1] - white is -1
734
- * @param {number} [rgbaAdditive=0] - black is 0
755
+ * @param {number} [rgba] - white is -1
756
+ * @param {number} [rgbaAdditive] - black is 0
735
757
  * @memberof WebGL */
736
758
  function glDraw(x, y, sizeX, sizeY, angle=0, uv0X=0, uv0Y=0, uv1X=1, uv1Y=1, rgba=-1, rgbaAdditive=0)
737
759
  {