littlejsengine 1.16.1 → 1.17.1

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 (52) hide show
  1. package/dist/littlejs.d.ts +287 -240
  2. package/dist/littlejs.esm.js +1419 -1259
  3. package/dist/littlejs.esm.min.js +1 -1
  4. package/dist/littlejs.js +1076 -910
  5. package/dist/littlejs.min.js +1 -1
  6. package/dist/littlejs.release.js +977 -815
  7. package/examples/box2d/gameObjects.js +6 -6
  8. package/examples/breakout/game.js +5 -6
  9. package/examples/electron/index.html +2 -2
  10. package/examples/electron/tiles.png +0 -0
  11. package/examples/htmlMenu/tiles.png +0 -0
  12. package/examples/index.html +1 -1
  13. package/examples/logo.png +0 -0
  14. package/examples/logo2.png +0 -0
  15. package/examples/module/tiles.png +0 -0
  16. package/examples/platformer/gameEffects.js +24 -23
  17. package/examples/platformer/gameLevel.js +24 -25
  18. package/examples/shorts/base.html +2 -1
  19. package/examples/shorts/clock.js +3 -3
  20. package/examples/shorts/fontImage.js +4 -3
  21. package/examples/shorts/parallax.js +1 -1
  22. package/examples/shorts/sequencer.js +1 -1
  23. package/examples/shorts/shapes.js +1 -1
  24. package/examples/shorts/texture.js +10 -6
  25. package/examples/shorts/tiles.png +0 -0
  26. package/examples/shorts/tiltedView.js +2 -0
  27. package/examples/starter/index.html +3 -2
  28. package/examples/starter/tiles.png +0 -0
  29. package/examples/typescript/tiles.png +0 -0
  30. package/examples/uiSystem/game.js +1 -1
  31. package/examples/uiSystem/tiles.png +0 -0
  32. package/package.json +1 -1
  33. package/plugins/postProcess.js +47 -28
  34. package/plugins/uiSystem.js +16 -16
  35. package/reference.md +6 -6
  36. package/src/engine.js +186 -198
  37. package/src/engineAudio.js +6 -10
  38. package/src/engineBuild.js +1 -0
  39. package/src/engineDebug.js +100 -98
  40. package/src/engineDraw.js +185 -148
  41. package/src/engineExport.js +327 -333
  42. package/src/engineFont.png +0 -0
  43. package/src/engineInput.js +17 -26
  44. package/src/engineMath.js +1112 -0
  45. package/src/engineMedals.js +4 -4
  46. package/src/engineObject.js +27 -27
  47. package/src/engineParticles.js +2 -2
  48. package/src/engineRelease.js +1 -3
  49. package/src/engineSettings.js +2 -2
  50. package/src/engineTileLayer.js +200 -176
  51. package/src/engineUtilities.js +48 -1097
  52. package/src/engineWebGL.js +127 -79
@@ -76,7 +76,7 @@ export function spawnRandomEdges()
76
76
  edgePoints.push(vec2(40,0));
77
77
  for (let i=40, y=0; i--;)
78
78
  edgePoints.push(vec2(i, y=LJS.clamp(y+LJS.rand(-2,2),0,5)));
79
- edgePoints.push(vec2(0,0));
79
+ edgePoints.push(vec2());
80
80
  const o = new LJS.Box2dStaticObject;
81
81
  o.addEdgeList(edgePoints);
82
82
  }
@@ -478,11 +478,11 @@ export function explosion(pos, radius=3, strength=300)
478
478
 
479
479
  // fire
480
480
  new LJS.ParticleEmitter(
481
- pos, 0, // pos, angle
482
- radius, .1, 100*radius, 3.14, // emitSize, emitTime, rate, cone
483
- Game.spriteAtlas.dot, // tileInfo
484
- hsl(0,1,.5), hsl(.15,1,.5), // colorStartA, colorStartB
485
- hsl(0,1,.5,0), hsl(.1, 1,.5,0), // colorEndA, colorEndB
481
+ pos, 0, // pos, angle
482
+ radius, .1, 100*radius, 3.14, // emitSize, emitTime, rate, cone
483
+ Game.spriteAtlas.dot, // tileInfo
484
+ hsl(0,.8,.5), hsl(.15,.8,.5), // colorStartA, colorStartB
485
+ hsl(0,1,.5,0), hsl(.1, 1,.5,0),// colorEndA, colorEndB
486
486
  .7, 1, .5, .1, .1, // time, sizeStart, sizeEnd, speed, angleSpeed
487
487
  .9, 1, 0, 3.14, .05, // damp, angleDamp, gravity, particleCone, fade
488
488
  1, 0, 1, 0, 1e9 // randomness, collide, additive, colorLinear, renderOrder
@@ -103,13 +103,12 @@ function gameRender()
103
103
  function gameRenderPost()
104
104
  {
105
105
  // use built in image font for text
106
- const font = new LJS.FontImage;
107
-
108
- font.drawText('Score: ' + score, LJS.cameraPos.add(vec2(0,9.7)), .15, true);
106
+ const font = LJS.engineFontImage;
107
+ font.drawText('Score: ' + score, LJS.cameraPos.add(vec2(0,9.2)), 1);
109
108
  if (!brickCount)
110
- font.drawText('You Win!', LJS.cameraPos.add(vec2(0,-5)), .2, true);
109
+ font.drawText('You Win!', LJS.cameraPos.add(vec2(0,-5)), 2);
111
110
  else if (!ball)
112
- font.drawText('Click to Play', LJS.cameraPos.add(vec2(0,-5)), .2, true);
111
+ font.drawText('Click to Play', LJS.cameraPos.add(vec2(0,-5)), 2);
113
112
  }
114
113
 
115
114
  ///////////////////////////////////////////////////////////////////////////////
@@ -138,7 +137,7 @@ function setupPostProcess()
138
137
 
139
138
  // scan lines
140
139
  const float scanlineScale = 2.;
141
- const float scanlineAlpha = .3;
140
+ const float scanlineAlpha = .6;
142
141
  c *= 1. - scanlineAlpha*cos(p.y*2.*iResolution.y/scanlineScale);
143
142
 
144
143
  {
@@ -7,7 +7,7 @@
7
7
  </head><body>
8
8
 
9
9
  <!-- LittleJS Engine -->
10
- <script src=../../dist/littlejs.js?1.16.1></script>
10
+ <script src=../../dist/littlejs.js?1.17.1></script>
11
11
 
12
12
  <!-- Add your game scripts here -->
13
- <script src=game.js?1.16.1></script>
13
+ <script src=game.js?1.17.1></script>
Binary file
Binary file
@@ -113,7 +113,6 @@ const exampleList =
113
113
  new ExampleInfo('Piano', 'piano.js', 'Interactive piano keyboard', false, 'music, sound, audio, notes, ui, instrument'),
114
114
  new ExampleInfo('Step Sequencer', 'sequencer.js', 'Simple music loop creation tool', false, 'music, sound, audio, notes, ui, instrument'),
115
115
  new ExampleInfo('Music Player', 'musicPlayer.js', 'Music player with audio seeking and drag and drop', false, 'sound, loading, audio, ui'),
116
- new ExampleInfo('WebGL Shader', 'shader.js', 'Full canvas webgl shader', false, 'webgl, visual, effect'),
117
116
  new ExampleInfo('--- MINI GAMES ---'),
118
117
  new ExampleInfo('Pong Game', 'pongGame.js', 'Classic paddle ball bouncing', false, 'objects, collision'),
119
118
  new ExampleInfo('Platformer Game', 'platformer.js', 'Jump and run side view', false, 'objects, gravity, level, tiles, camera'),
@@ -129,6 +128,7 @@ const exampleList =
129
128
  new ExampleInfo('Box2d Demo', 'box2d.js', 'Box2D physics plugin', false, 'objects, mouse'),
130
129
  new ExampleInfo('Box2d Car', 'box2dCar.js', 'Drivable car with Box2D physics', false, 'objects, vehicle, suspension, wheels'),
131
130
  new ExampleInfo('Box2d Pool', 'box2dPool.js', 'Billiard table pool game with physics', false, 'objects, game'),
131
+ new ExampleInfo('WebGL Shader', 'shader.js', 'Full canvas webgl shader', false, 'webgl, visual, effect'),
132
132
  new ExampleInfo('Post Processing', 'postProcess.js', 'Shader effects and filters', false, 'webgl, visual, effect'),
133
133
  new ExampleInfo('UI System', 'uiSystem.js', 'Buttons, sliders, and checkboxes', false, 'objects, widgets, interactive'),
134
134
  new ExampleInfo('Nine Slice', 'nineSlice.js', 'Scalable UI panels', false, 'three slice, stretch, corners, text, tiles'),
package/examples/logo.png CHANGED
Binary file
Binary file
Binary file
@@ -43,8 +43,6 @@ export const persistentParticleDestroyCallback = (particle)=>
43
43
  if (particle.groundObject)
44
44
  {
45
45
  GameLevel.foregroundTileLayer.drawTile(particle.pos, particle.size, particle.tileInfo, particle.color, particle.angle, particle.mirror);
46
- // update WebGL texture
47
- GameLevel.foregroundTileLayer.useWebGL();
48
46
  }
49
47
  }
50
48
 
@@ -74,26 +72,27 @@ export function explosion(pos, radius=3)
74
72
 
75
73
  sound_explosion.play(pos);
76
74
 
77
- // destroy level
78
- for (let x = -radius; x < radius; ++x)
79
75
  {
80
- const h = (radius*radius - x*x)**.5;
81
- for (let y = -h; y <= h; ++y)
82
- destroyTile(pos.add(vec2(x,y)), 0, 0);
83
- }
84
-
85
- // cleanup neighbors
86
- const cleanupRadius = radius + 2;
87
- for (let x = -cleanupRadius; x < cleanupRadius; ++x)
88
- {
89
- const h = (cleanupRadius**2 - x**2)**.5;
90
- for (let y = -h; y < h; ++y)
91
- GameLevel.decorateTile(pos.add(vec2(x,y)).floor());
76
+ // destroy level
77
+ const layer = GameLevel.tileLayers[1];
78
+ layer.redrawStart();
79
+ for (let x = -radius; x < radius; ++x)
80
+ {
81
+ const h = (radius*radius - x*x)**.5;
82
+ for (let y = -h; y <= h; ++y)
83
+ destroyTile(pos.add(vec2(x,y)), 0, 0);
84
+ }
85
+ // cleanup neighbors
86
+ const cleanupRadius = radius + 2;
87
+ for (let x = -cleanupRadius; x < cleanupRadius; ++x)
88
+ {
89
+ const h = (cleanupRadius**2 - x**2)**.5;
90
+ for (let y = -h; y < h; ++y)
91
+ GameLevel.decorateTile(pos.add(vec2(x,y)).floor(), layer);
92
+ }
93
+ layer.redrawEnd();
92
94
  }
93
95
 
94
- // update WebGL texture
95
- GameLevel.foregroundTileLayer.useWebGL();
96
-
97
96
  // kill/push objects
98
97
  LJS.engineObjectsCallback(pos, radius*3, (o)=>
99
98
  {
@@ -128,7 +127,7 @@ export function explosion(pos, radius=3)
128
127
  pos, 0, // pos, angle
129
128
  radius/2, .1, 100*radius, 3.14, // emitSize, emitTime, rate, cone
130
129
  0, // tileInfo
131
- rgb(1,.5,.1), rgb(1,.1,.1), // colorStartA, colorStartB
130
+ rgb(1,.5,.1), rgb(1,.1,.1), // colorStartA, colorStartB
132
131
  rgb(1,.5,.1,0), rgb(1,.1,.1,0), // colorEndA, colorEndB
133
132
  .7, .8, .2, .2, .05, // time, sizeStart, sizeEnd, speed, angleSpeed
134
133
  .9, 1, -.2, 3.14, .05, // damp, angleDamp, gravity, particleCone, fade
@@ -165,10 +164,12 @@ export function destroyTile(pos, makeSound = 1, cleanup = 1)
165
164
  // cleanup neighbors and rebuild WebGL
166
165
  if (cleanup)
167
166
  {
167
+ const layer = GameLevel.tileLayers[1];
168
+ layer.redrawStart();
168
169
  for (let i=-1;i<=1;++i)
169
170
  for (let j=-1;j<=1;++j)
170
- GameLevel.decorateTile(pos.add(vec2(i,j)));
171
- layer.useWebGL();
171
+ GameLevel.decorateTile(pos.add(vec2(i,j)), layer);
172
+ layer.redrawEnd();
172
173
  }
173
174
 
174
175
  return true;
@@ -260,7 +261,7 @@ export class ParallaxLayer extends LJS.CanvasLayer
260
261
  this.context.clearRect(0,0,1,h);
261
262
 
262
263
  // make WebGL texture
263
- this.useWebGL();
264
+ this.updateWebGL();
264
265
  }
265
266
 
266
267
  render()
@@ -126,28 +126,25 @@ function loadLevelData()
126
126
  }
127
127
  }
128
128
  }
129
+
130
+ tileLayer.onRedraw = ()=>
131
+ {
132
+ // apply decoration to level tiles
133
+ for (let x=levelSize.x; x--;)
134
+ for (let y=levelSize.y; y--;)
135
+ decorateTile(vec2(x,y), tileLayer);
136
+ }
129
137
  tileLayer.redraw();
130
138
  }
131
-
132
- // apply decoration to all level tiles
133
- const pos = vec2();
134
- const layerCount = tileMapData.layers.length;
135
- for (let layer=layerCount; layer--;)
136
- {
137
- for (pos.x=levelSize.x; pos.x--;)
138
- for (pos.y=levelSize.y; pos.y--;)
139
- decorateTile(pos, layer);
140
- tileLayers[layer].useWebGL();
141
- }
142
139
  }
143
140
 
144
- export function decorateTile(pos, layer=1)
141
+ export function decorateTile(pos, tileLayer)
145
142
  {
146
143
  LJS.ASSERT((pos.x|0) == pos.x && (pos.y|0)== pos.y);
147
- const tileLayer = tileLayers[layer];
148
144
  if (!tileLayer)
149
145
  return;
150
146
 
147
+ const w = tileLayer.tileInfo.size.x;
151
148
  if (tileLayer == foregroundTileLayer)
152
149
  {
153
150
  const tileType = tileLayer.getCollisionData(pos);
@@ -167,12 +164,11 @@ export function decorateTile(pos, layer=1)
167
164
 
168
165
  // make pixel perfect outlines
169
166
  const size = i&1 ? vec2(2, 16) : vec2(16, 2);
170
- tileLayer.context.fillStyle = levelOutlineColor.mutate(.1);
171
167
  const drawPos = pos.scale(16)
172
168
  .add(vec2(i==1?14:0,(i==0?14:0)))
173
169
  .subtract((i&1? vec2(0,8-size.y/2) : vec2(8-size.x/2,0)));
174
- tileLayer.context.fillRect(
175
- drawPos.x, tileLayer.canvas.height - drawPos.y, size.x, -size.y);
170
+ const color = levelOutlineColor.mutate(.1);
171
+ tileLayer.drawLayerRect(drawPos, size, color);
176
172
  }
177
173
  }
178
174
  else
@@ -185,15 +181,18 @@ export function decorateTile(pos, layer=1)
185
181
  const neighborTileDataB = tileLayer.getData(pos.add(vec2().setDirection((i+1)%4))).tile;
186
182
  if (neighborTileDataA > 0 || neighborTileDataB > 0)
187
183
  continue;
188
-
189
- const directionVector = vec2().setAngle((i+.5)*LJS.PI/2, 10).floor();
190
- const drawPos = pos.add(vec2(.5)) // center
191
- .scale(16).add(directionVector).floor(); // direction offset
192
-
193
- // clear rect without any scaling to prevent blur from filtering
194
- const s = 2;
195
- tileLayer.context.clearRect(
196
- drawPos.x - s/2, tileLayer.canvas.height - drawPos.y - s/2, s, s);
184
+
185
+ // get direction of corner
186
+ const directionVector = vec2();
187
+ if (i==0) directionVector.set(w-1,w-1);
188
+ if (i==1) directionVector.set(w-1,1);
189
+ if (i==2) directionVector.set(1,1);
190
+ if (i==3) directionVector.set(1,w-1);
191
+
192
+ // clear rect from corner
193
+ const s = vec2(2);
194
+ const drawPos = pos.scale(w).add(directionVector).subtract(s.scale(.5));
195
+ tileLayer.clearLayerRect(drawPos, s);
197
196
  }
198
197
  }
199
198
  }
@@ -1,10 +1,11 @@
1
1
  <!DOCTYPE html><meta charset=utf-8><body>
2
- <script src=../../dist/littlejs.js?1.16.1></script>
2
+ <script src=../../dist/littlejs.js?1.17.1></script>
3
3
  <script src=../../dist/box2d.wasm.js></script>
4
4
 
5
5
  <!-- LittleJS Engine Source
6
6
  <script src=../../src/engine.js></script>
7
7
  <script src=../../src/engineDebug.js></script>
8
+ <script src=../../src/engineMath.js></script>
8
9
  <script src=../../src/engineUtilities.js></script>
9
10
  <script src=../../src/engineSettings.js></script>
10
11
  <script src=../../src/engineObject.js></script>
@@ -15,7 +15,7 @@ function gameRender()
15
15
  const h = (d.slice(0,2)|0) + m/60;
16
16
 
17
17
  // draw clock hands
18
- drawLine(vec2(0,0), vec2(0,4).rotate(h/12*2*PI), 1);
19
- drawLine(vec2(0,0), vec2(0,6).rotate(m/60*2*PI), .4);
20
- drawLine(vec2(0,0), vec2(0,8).rotate(s/60*2*PI), .1);
18
+ drawLine(vec2(), vec2(0,4).rotate(h/12*2*PI), 1);
19
+ drawLine(vec2(), vec2(0,6).rotate(m/60*2*PI), .4);
20
+ drawLine(vec2(), vec2(0,8).rotate(s/60*2*PI), .1);
21
21
  }
@@ -1,8 +1,8 @@
1
1
  function gameRender()
2
2
  {
3
3
  // draw text with built in engine font image
4
- const font = new FontImage;
5
- font.drawText('Engine Font Test', cameraPos.add(vec2(0,3)), .2);
4
+ const font = engineFontImage
5
+ font.drawText('Engine Font', vec2(0,3), 2);
6
6
 
7
7
  // show every character in the font
8
8
  let s = '';
@@ -12,5 +12,6 @@ function gameRender()
12
12
  s += '\n';
13
13
  s += String.fromCharCode(i);
14
14
  }
15
- font.drawText(s, cameraPos, .1);
15
+
16
+ font.drawText(s, vec2());
16
17
  }
@@ -53,7 +53,7 @@ class ParallaxLayer extends CanvasLayer
53
53
  this.context.clearRect(0,0,1,h);
54
54
 
55
55
  // make WebGL texture
56
- this.useWebGL();
56
+ this.updateWebGL();
57
57
  }
58
58
 
59
59
  render()
@@ -72,7 +72,7 @@ function gameInit()
72
72
  new UISystemPlugin;
73
73
  uiSystem.defaultCornerRadius = 8;
74
74
  uiSystem.defaultShadowColor = BLACK;
75
- canvasClearColor = hsl(0,0,.3);
75
+ canvasClearColor = GRAY;
76
76
 
77
77
  // create sequencer buttons
78
78
  for (let step=stepCount; step--;)
@@ -7,7 +7,7 @@ function gameRender()
7
7
 
8
8
  // polygon shapes
9
9
  drawRectGradient(vec2(-6,0), vec2(5,4), RED, BLUE)
10
- drawRegularPoly(vec2(0,0), vec2(4), 3, PURPLE, .3, WHITE, time);
10
+ drawRegularPoly(vec2(), vec2(4), 3, PURPLE, .3, WHITE, time);
11
11
  let starPath = []
12
12
  for (let i=10; i--;)
13
13
  starPath.push(vec2(0,2*(i%2?.4:1)).rotate(i/10*PI*2));
@@ -1,12 +1,16 @@
1
1
  function gameRender()
2
2
  {
3
3
  // show the full texture
4
- let pos = vec2(0,0); // world position to draw
5
- let size = vec2(15); // world size of the tile
6
- let color = hsl(0,0,1); // color to multiply the tile by
7
- let tilePos = vec2(0,0); // top left corner in pixels
8
- let tileSize = vec2(256); // source size in pixels
4
+ let pos = vec2(); // world position to draw
5
+ let size = vec2(15); // world size of the tile
6
+ let color = hsl(0,0,1); // color to multiply the tile by
7
+ let tilePos = vec2(); // top left corner in pixels
8
+ let tileSize = vec2(256); // source size in pixels
9
9
  let tileInfo = new TileInfo(tilePos, tileSize); // tile info
10
- drawRect(pos, size, GRAY); // draw background
10
+
11
+ // draw background
12
+ drawRect(pos, size, GRAY);
13
+
14
+ // draw the tile
11
15
  drawTile(pos, size, tileInfo, color);
12
16
  }
Binary file
@@ -19,6 +19,8 @@ class Player extends GameObject
19
19
  {
20
20
  update()
21
21
  {
22
+ super.update();
23
+
22
24
  // apply movement controls
23
25
  const moveInput = keyDirection().clampLength(1).scale(.2);
24
26
  this.velocity = this.velocity.add(moveInput);
@@ -7,11 +7,12 @@
7
7
  </head><body>
8
8
 
9
9
  <!-- LittleJS Engine -->
10
- <script src=../../dist/littlejs.js?1.16.1></script>
10
+ <script src=../../dist/littlejs.js?1.17.1></script>
11
11
 
12
12
  <!-- LittleJS Engine Source
13
13
  <script src=../../src/engine.js></script>
14
14
  <script src=../../src/engineDebug.js></script>
15
+ <script src=../../src/engineMath.js></script>
15
16
  <script src=../../src/engineUtilities.js></script>
16
17
  <script src=../../src/engineSettings.js></script>
17
18
  <script src=../../src/engineObject.js></script>
@@ -31,4 +32,4 @@
31
32
  -->
32
33
 
33
34
  <!-- Add your game scripts here -->
34
- <script src=game.js?1.16.1></script>
35
+ <script src=game.js?1.17.1></script>
Binary file
Binary file
@@ -38,7 +38,7 @@ function createUI()
38
38
  // setup example menu
39
39
  uiMenu = new LJS.UIObject(vec2(0,500));
40
40
  uiRoot.addChild(uiMenu);
41
- const uiBackground = new LJS.UIObject(vec2(0,0), vec2(450,580));
41
+ const uiBackground = new LJS.UIObject(vec2(), vec2(450,580));
42
42
  uiBackground.lineWidth = 8;
43
43
  uiMenu.addChild(uiBackground);
44
44
 
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "littlejsengine",
3
- "version": "1.16.1",
3
+ "version": "1.17.1",
4
4
  "description": "LittleJS - Tiny and Fast HTML5 Game Engine",
5
5
  "main": "dist/littlejs.esm.js",
6
6
  "types": "dist/littlejs.d.ts",
@@ -24,14 +24,16 @@ class PostProcessPlugin
24
24
  {
25
25
  /** Create global post processing shader
26
26
  * @param {string} shaderCode
27
- * @param {boolean} [includeMainCanvas]
28
- * @example
29
- * // create the post process plugin object
30
- * new PostProcessPlugin(shaderCode);
31
- */
32
- constructor(shaderCode, includeMainCanvas=true)
27
+ * @param {boolean} [includeMainCanvas] - combine mainCanvs onto glCanvas
28
+ * @param {boolean} [feedbackTexture] - use glCanvas from previous frame as the texture
29
+ * @example
30
+ * // create the post process plugin object
31
+ * new PostProcessPlugin(shaderCode);
32
+ */
33
+ constructor(shaderCode, includeMainCanvas=false, feedbackTexture=false)
33
34
  {
34
35
  ASSERT(!postProcess, 'Post process already initialized');
36
+ ASSERT(!(includeMainCanvas && feedbackTexture), 'Post process cannot both include main canvas and use feedback texture');
35
37
  postProcess = this;
36
38
 
37
39
  if (!shaderCode) // default shader pass through
@@ -39,9 +41,10 @@ class PostProcessPlugin
39
41
 
40
42
  /** @property {WebGLProgram} - Shader for post processing */
41
43
  this.shader = undefined;
42
-
43
44
  /** @property {WebGLTexture} - Texture for post processing */
44
45
  this.texture = undefined;
46
+ /** @property {WebGLVertexArrayObject} - Vertex array object */
47
+ this.vao = undefined;
45
48
 
46
49
  // setup the post processing plugin
47
50
  initPostProcess();
@@ -50,7 +53,6 @@ class PostProcessPlugin
50
53
  function initPostProcess()
51
54
  {
52
55
  if (headlessMode) return;
53
-
54
56
  if (!glEnable)
55
57
  {
56
58
  console.warn('PostProcessPlugin: WebGL not enabled!');
@@ -61,14 +63,14 @@ class PostProcessPlugin
61
63
  postProcess.texture = glCreateTexture();
62
64
  postProcess.shader = glCreateProgram(
63
65
  '#version 300 es\n' + // specify GLSL ES version
64
- 'precision highp float;'+ // use highp for better accuracy
66
+ 'precision highp float;'+ // use highp for accuracy
65
67
  'in vec2 p;'+ // position
66
68
  'void main(){'+ // shader entry point
67
69
  'gl_Position=vec4(p+p-1.,1,1);'+ // set position
68
70
  '}' // end of shader
69
71
  ,
70
72
  '#version 300 es\n' + // specify GLSL ES version
71
- 'precision highp float;'+ // use highp for better accuracy
73
+ 'precision highp float;'+ // use highp for accuracy
72
74
  'uniform sampler2D iChannel0;'+ // input texture
73
75
  'uniform vec3 iResolution;'+ // size of output texture
74
76
  'uniform float iTime;'+ // time
@@ -79,6 +81,17 @@ class PostProcessPlugin
79
81
  'c.a=1.;'+ // always use full alpha
80
82
  '}' // end of shader
81
83
  );
84
+
85
+ // setup VAO for post processing
86
+ postProcess.vao = glContext.createVertexArray();
87
+ glContext.bindVertexArray(postProcess.vao);
88
+ glContext.bindBuffer(glContext.ARRAY_BUFFER, glGeometryBuffer);
89
+
90
+ // configure vertex attributes
91
+ const vertexByteStride = 8;
92
+ const pLocation = glContext.getAttribLocation(postProcess.shader, 'p');
93
+ glContext.enableVertexAttribArray(pLocation);
94
+ glContext.vertexAttribPointer(pLocation, 2, glContext.FLOAT, false, vertexByteStride, 0);
82
95
  }
83
96
  function postProcessContextLost()
84
97
  {
@@ -93,14 +106,17 @@ class PostProcessPlugin
93
106
  }
94
107
  function postProcessRender()
95
108
  {
96
- if (headlessMode) return;
97
-
98
- if (!glEnable)
99
- return;
109
+ if (headlessMode || !glEnable) return;
100
110
 
101
111
  // clear out the buffer
102
112
  glFlush();
103
-
113
+
114
+ // setup shader program to draw a quad
115
+ glContext.useProgram(postProcess.shader);
116
+ glContext.bindVertexArray(postProcess.vao);
117
+ glContext.pixelStorei(glContext.UNPACK_FLIP_Y_WEBGL, true);
118
+ glContext.disable(glContext.BLEND);
119
+
104
120
  // setup texture
105
121
  glContext.activeTexture(glContext.TEXTURE0);
106
122
  glContext.bindTexture(glContext.TEXTURE_2D, postProcess.texture);
@@ -111,29 +127,32 @@ class PostProcessPlugin
111
127
  workCanvas.height = mainCanvasSize.y;
112
128
  glCopyToContext(workContext);
113
129
  workContext.drawImage(mainCanvas, 0, 0);
130
+ mainCanvas.width |= 0
114
131
 
115
132
  // copy work canvas to texture
116
133
  glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, workCanvas);
117
134
  }
118
-
119
- // setup shader program to draw a quad
120
- glContext.useProgram(postProcess.shader);
121
- glContext.bindBuffer(glContext.ARRAY_BUFFER, glGeometryBuffer);
122
- glContext.pixelStorei(glContext.UNPACK_FLIP_Y_WEBGL, 1);
123
- glContext.disable(glContext.BLEND);
124
-
125
- // set vertex position attribute
126
- const vertexByteStride = 8;
127
- const pLocation = glContext.getAttribLocation(postProcess.shader, 'p');
128
- glContext.enableVertexAttribArray(pLocation);
129
- glContext.vertexAttribPointer(pLocation, 2, glContext.FLOAT, false, vertexByteStride, 0);
130
-
135
+ else if (!feedbackTexture)
136
+ {
137
+ // copy glCanvas to texture
138
+ glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, glCanvas);
139
+ }
140
+
131
141
  // set uniforms and draw
132
142
  const uniformLocation = (name)=>glContext.getUniformLocation(postProcess.shader, name);
133
143
  glContext.uniform1i(uniformLocation('iChannel0'), 0);
134
144
  glContext.uniform1f(uniformLocation('iTime'), time);
135
145
  glContext.uniform3f(uniformLocation('iResolution'), mainCanvas.width, mainCanvas.height, 1);
136
146
  glContext.drawArrays(glContext.TRIANGLE_STRIP, 0, 4);
147
+
148
+ if (feedbackTexture)
149
+ {
150
+ // pass glCanvas back to overlay texture
151
+ glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, glCanvas);
152
+ }
153
+
154
+ // force it to set instanced mode
155
+ glSetInstancedMode(true);
137
156
  }
138
157
  }
139
158
  }