littlejsengine 1.18.29 → 1.20.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 (51) hide show
  1. package/FAQ.md +841 -815
  2. package/README.md +211 -199
  3. package/dist/littlejs.d.ts +4383 -812
  4. package/dist/littlejs.esm.js +31848 -16680
  5. package/dist/littlejs.esm.min.js +14 -1
  6. package/dist/littlejs.js +31230 -16166
  7. package/dist/littlejs.min.js +13 -1
  8. package/dist/littlejs.release.js +27419 -15457
  9. package/package.json +10 -5
  10. package/plugins/audioEffects.js +375 -0
  11. package/plugins/box2d.js +2516 -2073
  12. package/plugins/drawUtilities.js +206 -31
  13. package/plugins/gltf.js +740 -0
  14. package/plugins/jsconfig.json +19 -0
  15. package/plugins/lightSystem.js +719 -330
  16. package/plugins/math3d.js +911 -0
  17. package/plugins/medalSystem.js +118 -72
  18. package/plugins/newgrounds.js +400 -199
  19. package/plugins/pathFinder.js +208 -175
  20. package/plugins/pluginExport.js +196 -115
  21. package/plugins/postProcess.js +284 -166
  22. package/plugins/render3d.js +4072 -0
  23. package/plugins/render3dDebug.js +109 -0
  24. package/plugins/render3dExtras.js +1754 -0
  25. package/plugins/render3dVoxels.js +502 -0
  26. package/plugins/textureSheet.js +86 -48
  27. package/plugins/threejs.js +183 -158
  28. package/plugins/tweakables.js +411 -0
  29. package/plugins/tweenSystem.js +646 -526
  30. package/plugins/uiSystem.js +2024 -1687
  31. package/plugins/zzfxm.js +8 -15
  32. package/src/engine.js +345 -194
  33. package/src/engineAudio.js +1022 -777
  34. package/src/engineBuild.mjs +289 -253
  35. package/src/engineDebug.js +912 -735
  36. package/src/engineDraw.js +1774 -1510
  37. package/src/engineEditor.js +2431 -0
  38. package/src/engineExport.js +419 -396
  39. package/src/engineInput.js +1462 -1293
  40. package/src/engineLogo.js +4 -3
  41. package/src/engineMath.js +1274 -1183
  42. package/src/engineObject.js +674 -551
  43. package/src/engineParticles.js +583 -532
  44. package/src/engineRelease.js +67 -45
  45. package/src/engineSettings.js +808 -726
  46. package/src/engineTileLayer.js +995 -741
  47. package/src/engineUtilities.js +32 -13
  48. package/src/engineWebGL.js +1162 -941
  49. package/src/jsconfig.json +17 -13
  50. package/plugins/box2d.wasm.js +0 -630
  51. package/plugins/box2d.wasm.wasm +0 -0
@@ -1,166 +1,284 @@
1
- /**
2
- * LittleJS Post Processing Plugin
3
- * - Supports shadertoy style post processing shaders
4
- * - call new PostProcessPlugin() to setup post processing
5
- * - can be enabled to pass other canvases through a final shader
6
- * @namespace PostProcess
7
- */
8
-
9
- 'use strict';
10
-
11
- ///////////////////////////////////////////////////////////////////////////////
12
-
13
- /** Global Post Process plugin object
14
- * @type {PostProcessPlugin}
15
- * @memberof PostProcess */
16
- let postProcess;
17
-
18
- /////////////////////////////////////////////////////////////////////////
19
- /**
20
- * Post Process Plugin - Applies a full screen shader to the rendered output
21
- * @memberof PostProcess
22
- */
23
- class PostProcessPlugin
24
- {
25
- /** Create global post processing shader
26
- * @param {string} shaderCode
27
- * @param {boolean} [includeMainCanvas] - combine mainCanvas 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)
34
- {
35
- ASSERT(!postProcess, 'Post process already initialized');
36
- ASSERT(!(includeMainCanvas && feedbackTexture), 'Post process cannot both include main canvas and use feedback texture');
37
- postProcess = this;
38
-
39
- if (!shaderCode) // default shader pass through
40
- shaderCode = 'void mainImage(out vec4 c,vec2 p){c=texture(iChannel0,p/iResolution.xy);}';
41
-
42
- /** @property {WebGLProgram} - Shader for post processing */
43
- this.shader = undefined;
44
- /** @property {WebGLTexture} - Texture for post processing */
45
- this.texture = undefined;
46
- /** @property {WebGLVertexArrayObject} - Vertex array object */
47
- this.vao = undefined;
48
-
49
- // setup the post processing plugin
50
- initPostProcess();
51
- engineAddPlugin(undefined, postProcessRender, postProcessContextLost, postProcessContextRestored);
52
-
53
- function initPostProcess()
54
- {
55
- if (headlessMode) return;
56
- if (!glEnable)
57
- {
58
- console.warn('PostProcessPlugin: WebGL not enabled!');
59
- return;
60
- }
61
-
62
- // create resources
63
- postProcess.texture = glCreateTexture();
64
- postProcess.shader = glCreateProgram(
65
- '#version 300 es\n' + // specify GLSL ES version
66
- 'precision highp float;'+ // use highp for accuracy
67
- 'in vec2 p;'+ // position
68
- 'void main(){'+ // shader entry point
69
- 'gl_Position=vec4(p+p-1.,1,1);'+ // set position
70
- '}' // end of shader
71
- ,
72
- '#version 300 es\n' + // specify GLSL ES version
73
- 'precision highp float;'+ // use highp for accuracy
74
- 'uniform sampler2D iChannel0;'+ // input texture
75
- 'uniform vec3 iResolution;'+ // size of output texture
76
- 'uniform float iTime;'+ // time
77
- 'out vec4 c;'+ // out color
78
- '\n' + shaderCode + '\n'+ // insert custom shader code
79
- 'void main(){'+ // shader entry point
80
- 'mainImage(c,gl_FragCoord.xy);'+ // call post process function
81
- 'c.a=1.;'+ // always use full alpha
82
- '}' // end of shader
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);
95
- }
96
- function postProcessContextLost()
97
- {
98
- postProcess.shader = undefined;
99
- postProcess.texture = undefined;
100
- LOG('PostProcessPlugin: WebGL context lost');
101
- }
102
- function postProcessContextRestored()
103
- {
104
- initPostProcess();
105
- LOG('PostProcessPlugin: WebGL context restored');
106
- }
107
- function postProcessRender()
108
- {
109
- if (headlessMode || !glEnable) return;
110
-
111
- // clear out the buffer
112
- glFlush();
113
-
114
- // ensure we render to the default framebuffer (in case any earlier
115
- // caller this frame left a render target bound)
116
- glContext.bindFramebuffer(glContext.FRAMEBUFFER, null);
117
-
118
- // setup shader program to draw a quad
119
- glContext.useProgram(postProcess.shader);
120
- glContext.bindVertexArray(postProcess.vao);
121
- glContext.pixelStorei(glContext.UNPACK_FLIP_Y_WEBGL, true);
122
- glContext.disable(glContext.BLEND);
123
-
124
- // setup texture
125
- glContext.activeTexture(glContext.TEXTURE0);
126
- glContext.bindTexture(glContext.TEXTURE_2D, postProcess.texture);
127
- if (includeMainCanvas)
128
- {
129
- // copy main canvas to work canvas
130
- workCanvas.width = mainCanvasSize.x;
131
- workCanvas.height = mainCanvasSize.y;
132
- glCopyToContext(workContext);
133
- workContext.drawImage(mainCanvas, 0, 0);
134
- mainCanvas.width |= 0; // setting size clears the main canvas
135
-
136
-
137
- // copy work canvas to texture
138
- glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, workCanvas);
139
- }
140
- else if (!feedbackTexture)
141
- {
142
- // copy glCanvas to texture
143
- glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, glCanvas);
144
- }
145
-
146
- // set uniforms and draw
147
- const uniformLocation = (name)=>glContext.getUniformLocation(postProcess.shader, name);
148
- glContext.uniform1i(uniformLocation('iChannel0'), 0);
149
- glContext.uniform1f(uniformLocation('iTime'), time);
150
- glContext.uniform3f(uniformLocation('iResolution'), mainCanvas.width, mainCanvas.height, 1);
151
- glContext.drawArrays(glContext.TRIANGLE_STRIP, 0, 4);
152
-
153
- if (feedbackTexture)
154
- {
155
- // pass glCanvas back to overlay texture
156
- glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, glCanvas);
157
- }
158
-
159
- // restore default so subsequent dynamic texture uploads aren't flipped
160
- glContext.pixelStorei(glContext.UNPACK_FLIP_Y_WEBGL, false);
161
-
162
- // force it to set instanced mode
163
- glSetInstancedMode(true);
164
- }
165
- }
166
- }
1
+ /**
2
+ * LittleJS Post Processing Plugin
3
+ * - Supports shadertoy style post processing shaders
4
+ * - call new PostProcessPlugin() to setup post processing
5
+ * - can be enabled to pass other canvases through a final shader
6
+ * - iResolution is the canvas backing store, so it grows with canvasPixelRatio
7
+ * like shadertoy does. Effects that use it only for uv (p/iResolution.xy) are
8
+ * unaffected, but ones that set a feature size from it, like scan lines, get
9
+ * finer as the ratio rises. Divide by getCanvasPixelRatio() to pin them.
10
+ * @namespace PostProcess
11
+ */
12
+
13
+ 'use strict';
14
+
15
+ ///////////////////////////////////////////////////////////////////////////////
16
+
17
+ /** Global Post Process plugin object
18
+ * @type {PostProcessPlugin}
19
+ * @memberof PostProcess */
20
+ let postProcess;
21
+
22
+ /////////////////////////////////////////////////////////////////////////
23
+ /**
24
+ * Post Process Plugin - Applies a full screen shader to the rendered output
25
+ * - Create it after any plugin that draws, since plugins render in the order they are made
26
+ * and this one shades what is on the canvas when its turn comes
27
+ * - It runs after gameRenderPost, so a HUD drawn there with WebGL is shaded (and bloomed) too;
28
+ * draw the HUD with useWebGL=false (the main canvas) or from a plugin created after this one
29
+ * @memberof PostProcess
30
+ */
31
+ class PostProcessPlugin
32
+ {
33
+ /** Create global post processing shader
34
+ * @param {string} [shaderCode] - Shadertoy style mainImage code, a pass-through when left out
35
+ * @param {boolean} [includeMainCanvas] - combine mainCanvas onto glCanvas
36
+ * @param {boolean} [feedbackTexture] - also pass the shader's own output from the previous frame as iChannel1,
37
+ * for trails and echoes; iChannel0 is still the frame just drawn
38
+ * @example
39
+ * // create the post process plugin object
40
+ * new PostProcessPlugin(shaderCode);
41
+ */
42
+ constructor(shaderCode, includeMainCanvas=false, feedbackTexture=false)
43
+ {
44
+ ASSERT(engineInitialized || headlessMode, 'create the plugin after engineInit, e.g. in gameInit');
45
+ ASSERT(!postProcess, 'Post process already initialized');
46
+ ASSERT(!(includeMainCanvas && feedbackTexture), 'Post process cannot both include main canvas and use feedback texture');
47
+ postProcess = this;
48
+
49
+ if (!shaderCode) // default shader pass through
50
+ shaderCode = 'void mainImage(out vec4 c,vec2 p){c=texture(iChannel0,p/iResolution.xy);}';
51
+
52
+ /** @property {WebGLProgram|undefined} - Shader for post processing
53
+ * @type {WebGLProgram|undefined} */
54
+ this.shader = undefined;
55
+ /** @property {WebGLTexture|undefined} - Texture for post processing
56
+ * @type {WebGLTexture|undefined} */
57
+ this.texture = undefined;
58
+ /** @property {WebGLTexture|undefined} - The previous frame's output, iChannel1, when feedbackTexture is set
59
+ * @type {WebGLTexture|undefined} */
60
+ this.feedbackTexture = undefined;
61
+ /** @property {WebGLVertexArrayObject|undefined} - Vertex array object
62
+ * @type {WebGLVertexArrayObject|undefined} */
63
+ this.vao = undefined;
64
+
65
+ // setup the post processing plugin
66
+ initPostProcess();
67
+ engineAddPlugin(undefined, postProcessRender, postProcessContextLost, postProcessContextRestored);
68
+
69
+ function initPostProcess()
70
+ {
71
+ if (headlessMode) return;
72
+ if (!glEnable)
73
+ {
74
+ console.warn('PostProcessPlugin: WebGL not enabled!');
75
+ return;
76
+ }
77
+
78
+ // create resources, the feedback starting black, as if the frame before the first were empty
79
+ if (feedbackTexture)
80
+ {
81
+ postProcess.feedbackTexture = glCreateTexture();
82
+ glContext.bindTexture(glContext.TEXTURE_2D, postProcess.feedbackTexture);
83
+ glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, 1, 1, 0, glContext.RGBA,
84
+ glContext.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 255]));
85
+ glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture);
86
+ }
87
+ postProcess.texture = glCreateTexture();
88
+ postProcess.shader = glCreateProgram(
89
+ '#version 300 es\n' + // specify GLSL ES version
90
+ 'precision highp float;'+ // use highp for accuracy
91
+ 'in vec2 p;'+ // position
92
+ 'void main(){'+ // shader entry point
93
+ 'gl_Position=vec4(p+p-1.,1,1);'+ // set position
94
+ '}' // end of shader
95
+ ,
96
+ '#version 300 es\n' + // specify GLSL ES version
97
+ 'precision highp float;'+ // use highp for accuracy
98
+ 'uniform sampler2D iChannel0;'+ // input texture
99
+ 'uniform sampler2D iChannel1;'+ // the previous frame's output, when feedbackTexture is set
100
+ 'uniform vec3 iResolution;'+ // size of output texture
101
+ 'uniform float iTime;'+ // time
102
+ 'out vec4 c;'+ // out color
103
+ '\n' + shaderCode + '\n'+ // insert custom shader code
104
+ 'void main(){'+ // shader entry point
105
+ 'mainImage(c,gl_FragCoord.xy);'+ // call post process function
106
+ 'c.a=1.;'+ // always use full alpha
107
+ '}' // end of shader
108
+ );
109
+
110
+ // setup VAO for post processing
111
+ postProcess.vao = glContext.createVertexArray();
112
+ glContext.bindVertexArray(postProcess.vao);
113
+ glContext.bindBuffer(glContext.ARRAY_BUFFER, glGeometryBuffer);
114
+
115
+ // configure vertex attributes
116
+ const vertexByteStride = 8;
117
+ const pLocation = glContext.getAttribLocation(postProcess.shader, 'p');
118
+ glContext.enableVertexAttribArray(pLocation);
119
+ glContext.vertexAttribPointer(pLocation, 2, glContext.FLOAT, false, vertexByteStride, 0);
120
+ }
121
+ function postProcessContextLost()
122
+ {
123
+ postProcess.shader = undefined;
124
+ postProcess.texture = undefined;
125
+ postProcess.feedbackTexture = undefined;
126
+ LOG('PostProcessPlugin: WebGL context lost');
127
+ }
128
+ function postProcessContextRestored()
129
+ {
130
+ initPostProcess();
131
+ LOG('PostProcessPlugin: WebGL context restored');
132
+ }
133
+ function postProcessRender()
134
+ {
135
+ if (headlessMode || !glEnable) return;
136
+
137
+ // made now if WebGL was off when the plugin was made, or when a lost context came back
138
+ if (!postProcess.shader)
139
+ {
140
+ if (glContext.isContextLost()) return;
141
+ initPostProcess();
142
+ }
143
+
144
+ // clear out the buffer
145
+ glFlush();
146
+
147
+ // ensure we render to the default framebuffer (in case any earlier
148
+ // caller this frame left a render target bound)
149
+ glContext.bindFramebuffer(glContext.FRAMEBUFFER, null);
150
+
151
+ // setup shader program to draw a quad
152
+ glContext.useProgram(postProcess.shader);
153
+ glContext.bindVertexArray(postProcess.vao);
154
+ glContext.pixelStorei(glContext.UNPACK_FLIP_Y_WEBGL, true);
155
+ // upload the canvas the way it shows, premultiplied, since the shader writes full alpha; unpremultiplied
156
+ // a see-through pixel would come out at its full brightness instead of faded over the background
157
+ glContext.pixelStorei(glContext.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
158
+ glContext.disable(glContext.BLEND);
159
+
160
+ // setup texture
161
+ glContext.activeTexture(glContext.TEXTURE0);
162
+ glContext.bindTexture(glContext.TEXTURE_2D, postProcess.texture);
163
+ if (includeMainCanvas)
164
+ {
165
+ // copy main canvas to work canvas at the backing store size,
166
+ // mainCanvasSize is css pixels so it would lose resolution
167
+ workCanvas.width = mainCanvas.width;
168
+ workCanvas.height = mainCanvas.height;
169
+ glCopyToContext(workContext);
170
+ workContext.drawImage(mainCanvas, 0, 0);
171
+ // clear the main canvas with clearRect, resizing it would also
172
+ // reset the context state (smoothing, line caps) for anything
173
+ // drawn after this and reallocate the canvas every frame
174
+ mainContext.save();
175
+ mainContext.setTransform(1, 0, 0, 1, 0, 0);
176
+ mainContext.clearRect(0, 0, mainCanvas.width, mainCanvas.height);
177
+ mainContext.restore();
178
+
179
+ // copy work canvas to texture
180
+ glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, workCanvas);
181
+ }
182
+ else
183
+ {
184
+ // copy glCanvas to texture
185
+ glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, glCanvas);
186
+ }
187
+
188
+ // the previous frame's output, on the second texture unit
189
+ if (feedbackTexture)
190
+ {
191
+ glContext.activeTexture(glContext.TEXTURE1);
192
+ glContext.bindTexture(glContext.TEXTURE_2D, postProcess.feedbackTexture);
193
+ }
194
+
195
+ // set uniforms and draw
196
+ const uniformLocation = (name)=>glUniformLocation(postProcess.shader, name);
197
+ glContext.uniform1i(uniformLocation('iChannel0'), 0);
198
+ glContext.uniform1i(uniformLocation('iChannel1'), 1);
199
+ glContext.uniform1f(uniformLocation('iTime'), time);
200
+ glContext.uniform3f(uniformLocation('iResolution'), mainCanvas.width, mainCanvas.height, 1);
201
+ glContext.drawArrays(glContext.TRIANGLE_STRIP, 0, 4);
202
+
203
+ if (feedbackTexture)
204
+ {
205
+ // keep this frame's output for the next one, then hand the first texture unit back to the engine
206
+ glContext.texImage2D(glContext.TEXTURE_2D, 0, glContext.RGBA, glContext.RGBA, glContext.UNSIGNED_BYTE, glCanvas);
207
+ glContext.activeTexture(glContext.TEXTURE0);
208
+ }
209
+
210
+ // restore defaults so subsequent dynamic texture uploads aren't flipped or premultiplied
211
+ glContext.pixelStorei(glContext.UNPACK_FLIP_Y_WEBGL, false);
212
+ glContext.pixelStorei(glContext.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
213
+
214
+ // bind back the texture the 2D batch thinks is bound, a plugin drawing after this one uses it
215
+ if (glActiveTexture)
216
+ glContext.bindTexture(glContext.TEXTURE_2D, glActiveTexture);
217
+
218
+ // force it to set instanced mode
219
+ glSetInstancedMode(true);
220
+ }
221
+ }
222
+ }
223
+
224
+ ///////////////////////////////////////////////////////////////////////////////
225
+
226
+ /**
227
+ * Shader code for a bloom effect, the bright parts of the image blurred back over it
228
+ * - Pass it to PostProcessPlugin, or edit the string to build an effect on top of it
229
+ * @param {number} [threshold] - Brightness where the glow starts, 0 is everything and 1 is only pure white
230
+ * @param {number} [strength] - How much glow to add
231
+ * @param {number} [size] - How far the glow spreads in pixels, which also sets how many samples it takes
232
+ * @return {string}
233
+ * @memberof PostProcess
234
+ */
235
+ function postProcessBloomShader(threshold=.6, strength=1, size=6)
236
+ {
237
+ ASSERT(isNumber(threshold) && isNumber(strength) && isNumber(size), 'bloom settings must be numbers');
238
+ ASSERT(size > 0, 'bloom size must be above zero');
239
+ ASSERT(size <= 32, 'a bloom this wide takes a sample every few pixels of every ring, which is hundreds of samples a pixel', size);
240
+
241
+ // Taps on three rings over a disc of the given size, one every three pixels or so of each ring
242
+ // so there is no gap wide enough to show. The count follows the ring all the way out: hold it
243
+ // still and a wider glow only spreads the same taps further apart, until they show up as the
244
+ // ring of evenly spaced copies a single ring of eight leaves around anything bright.
245
+ // Each ring has its own count, odd and unequal, and its own turn off the last, so the little
246
+ // the taps do miss comes out as fine ripple instead of a shape of its own.
247
+ const rings = 3;
248
+ let code = '', taps = 0;
249
+ for (let j = 0; j < rings; ++j)
250
+ {
251
+ const radius = ((j + .5) / rings) ** .5 * size; // equal area per ring
252
+ const count = max(5 + 2 * j, round(2 * radius)) | 1;
253
+ taps += count;
254
+ code += `
255
+ for (int k = 0; k < ${count}; ++k)
256
+ {
257
+ float a = float(k) * ${(2 * PI / count).toFixed(7)}${j ? ' + ' + (j * 2.3999632).toFixed(7) : ''};
258
+ glow += max(vec3(0), texture(iChannel0, uv + vec2(cos(a), sin(a)) * ${radius.toFixed(4)} / iResolution.xy).rgb - ${threshold.toFixed(4)});
259
+ }`;
260
+ }
261
+ return `
262
+ void mainImage(out vec4 color, vec2 pixel)
263
+ {
264
+ vec2 uv = pixel / iResolution.xy;
265
+ color = texture(iChannel0, uv);
266
+ vec3 glow = vec3(0);${code}
267
+ color.rgb += glow * ${(strength / taps).toFixed(6)};
268
+ }`;
269
+ }
270
+
271
+ /**
272
+ * Set up post processing with a bloom effect, so bright colors and lights glow
273
+ * @param {number} [threshold] - Brightness where the glow starts, 0 is everything and 1 is only pure white
274
+ * @param {number} [strength] - How much glow to add
275
+ * @param {number} [size] - How far the glow spreads in pixels
276
+ * @param {boolean} [includeMainCanvas] - Glow the 2D canvas too, off by default so HUD text stays crisp
277
+ * (a HUD drawn with WebGL in gameRenderPost glows either way, draw it with useWebGL=false)
278
+ * @return {PostProcessPlugin}
279
+ * @memberof PostProcess
280
+ * @example
281
+ * postProcessBloom(); // in gameInit, after any Render3DPlugin
282
+ */
283
+ function postProcessBloom(threshold=.6, strength=1, size=6, includeMainCanvas=false)
284
+ { return new PostProcessPlugin(postProcessBloomShader(threshold, strength, size), includeMainCanvas); }