p5 2.0.0 → 2.0.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 (188) hide show
  1. package/{src → dist}/accessibility/color_namer.js +48 -3
  2. package/{src → dist}/accessibility/describe.js +2 -2
  3. package/{src → dist}/accessibility/gridOutput.js +2 -2
  4. package/dist/accessibility/index.js +60 -0
  5. package/{src → dist}/accessibility/outputs.js +2 -2
  6. package/{src → dist}/accessibility/textOutput.js +2 -2
  7. package/dist/app.js +120 -0
  8. package/{src → dist}/color/color_conversion.js +48 -10
  9. package/{src → dist}/color/color_spaces/hsb.js +3 -1
  10. package/dist/color/creating_reading.js +3 -0
  11. package/dist/color/index.js +13 -0
  12. package/dist/color/p5.Color.culori.js +1 -0
  13. package/dist/color/p5.Color.js +3 -0
  14. package/{src → dist}/color/setting.js +9 -6
  15. package/{src/core/constants.js → dist/constants-C-g_eAdC.js} +266 -130
  16. package/{src → dist}/core/States.js +3 -1
  17. package/dist/core/constants.js +1 -0
  18. package/{src → dist}/core/environment.js +7 -6
  19. package/{src → dist}/core/friendly_errors/browser_errors.js +1 -1
  20. package/{src → dist}/core/friendly_errors/fes_core.js +14 -44
  21. package/{src → dist}/core/friendly_errors/file_errors.js +6 -3
  22. package/dist/core/friendly_errors/index.js +23 -0
  23. package/dist/core/friendly_errors/param_validator.js +5455 -0
  24. package/{src → dist}/core/friendly_errors/sketch_reader.js +50 -4
  25. package/{src → dist}/core/friendly_errors/sketch_verifier.js +6 -6
  26. package/{src → dist}/core/friendly_errors/stacktrace.js +3 -5
  27. package/{src → dist}/core/friendly_errors/validate_params.js +50 -41
  28. package/{src → dist}/core/helpers.js +9 -6
  29. package/dist/core/init.js +105 -0
  30. package/dist/core/internationalization.js +302 -0
  31. package/dist/core/legacy.js +73 -0
  32. package/dist/core/main.js +44 -0
  33. package/dist/core/noop.js +3 -0
  34. package/dist/core/p5.Graphics.js +40 -0
  35. package/dist/core/p5.Renderer.js +11 -0
  36. package/dist/core/p5.Renderer2D.js +44 -0
  37. package/dist/core/reference.js +1 -0
  38. package/dist/core/rendering.js +40 -0
  39. package/{src → dist}/core/structure.js +3 -3
  40. package/{src → dist}/core/transform.js +2 -2
  41. package/{src/color/creating_reading.js → dist/creating_reading-D4AAKRbx.js} +841 -13
  42. package/{src → dist}/data/index.js +3 -1
  43. package/{src → dist}/data/local_storage.js +2 -8
  44. package/{src → dist}/dom/dom.js +11 -5
  45. package/dist/dom/index.js +18 -0
  46. package/{src → dist}/dom/p5.Element.js +14 -12
  47. package/{src → dist}/dom/p5.File.js +4 -4
  48. package/{src → dist}/dom/p5.MediaElement.js +10 -4
  49. package/{src → dist}/events/acceleration.js +2 -2
  50. package/{src → dist}/events/index.js +3 -1
  51. package/{src → dist}/events/keyboard.js +14 -11
  52. package/{src → dist}/events/pointer.js +16 -17
  53. package/dist/image/const.js +9 -0
  54. package/{src → dist}/image/filterRenderer2D.js +57 -37
  55. package/{src → dist}/image/filters.js +1 -3
  56. package/dist/image/image.js +40 -0
  57. package/dist/image/index.js +51 -0
  58. package/dist/image/loading_displaying.js +40 -0
  59. package/dist/image/p5.Image.js +11 -0
  60. package/{src → dist}/image/pixels.js +4 -3
  61. package/{src → dist}/io/csv.js +72 -70
  62. package/dist/io/files.js +40 -0
  63. package/dist/io/index.js +51 -0
  64. package/{src → dist}/io/p5.Table.js +6 -6
  65. package/{src → dist}/io/p5.TableRow.js +3 -4
  66. package/{src → dist}/io/p5.XML.js +2 -5
  67. package/{src → dist}/io/utilities.js +1 -1
  68. package/{src/core/p5.Renderer2D.js → dist/main-s72KWcUy.js} +735 -57
  69. package/{src → dist}/math/Matrices/Matrix.js +10 -8
  70. package/{src → dist}/math/Matrices/MatrixInterface.js +5 -3
  71. package/{src → dist}/math/Matrices/MatrixNumjs.js +12 -26
  72. package/{src → dist}/math/calculation.js +2 -2
  73. package/{src → dist}/math/index.js +6 -3
  74. package/{src → dist}/math/math.js +2 -2
  75. package/{src → dist}/math/noise.js +2 -2
  76. package/{src → dist}/math/p5.Matrix.js +7 -4
  77. package/{src → dist}/math/p5.Vector.js +6 -6
  78. package/{src → dist}/math/random.js +2 -2
  79. package/{src → dist}/math/trigonometry.js +16 -15
  80. package/{src/image/p5.Image.js → dist/p5.Renderer-CwAYZOC2.js} +390 -19
  81. package/dist/rendering--aAe5aq3.js +24925 -0
  82. package/{src → dist}/shape/2d_primitives.js +18 -17
  83. package/{src → dist}/shape/attributes.js +18 -17
  84. package/{src → dist}/shape/curves.js +2 -2
  85. package/{src → dist}/shape/custom_shapes.js +44 -64
  86. package/{src → dist}/shape/index.js +10 -2
  87. package/{src → dist}/shape/vertex.js +2 -3
  88. package/dist/type/index.js +25 -0
  89. package/{src → dist}/type/lib/Typr.js +76 -94
  90. package/{src → dist}/type/p5.Font.js +37 -61
  91. package/{src → dist}/type/textCore.js +34 -57
  92. package/{src → dist}/type/unicodeRanges.js +3 -1
  93. package/{src → dist}/utilities/conversion.js +2 -2
  94. package/{src → dist}/utilities/index.js +3 -1
  95. package/{src → dist}/utilities/time_date.js +6 -7
  96. package/{src → dist}/utilities/utility_functions.js +2 -2
  97. package/dist/webgl/3d_primitives.js +40 -0
  98. package/{src → dist}/webgl/GeometryBufferCache.js +3 -1
  99. package/{src → dist}/webgl/GeometryBuilder.js +12 -8
  100. package/{src → dist}/webgl/ShaderGenerator.js +79 -82
  101. package/{src → dist}/webgl/ShapeBuilder.js +26 -23
  102. package/dist/webgl/index.js +76 -0
  103. package/{src → dist}/webgl/interaction.js +7 -6
  104. package/dist/webgl/light.js +40 -0
  105. package/{src → dist}/webgl/loading.js +45 -12
  106. package/dist/webgl/material.js +40 -0
  107. package/dist/webgl/p5.Camera.js +40 -0
  108. package/{src → dist}/webgl/p5.DataArray.js +3 -5
  109. package/dist/webgl/p5.Framebuffer.js +40 -0
  110. package/{src → dist}/webgl/p5.Geometry.js +12 -15
  111. package/{src → dist}/webgl/p5.Quat.js +5 -4
  112. package/{src → dist}/webgl/p5.RenderBuffer.js +2 -3
  113. package/dist/webgl/p5.RendererGL.js +40 -0
  114. package/dist/webgl/p5.Shader.js +40 -0
  115. package/dist/webgl/p5.Texture.js +40 -0
  116. package/{src → dist}/webgl/text.js +51 -9
  117. package/lib/p5.esm.js +102 -48
  118. package/lib/p5.js +102 -48
  119. package/lib/p5.min.js +1 -1
  120. package/package.json +17 -16
  121. package/translations/dev.js +6 -6
  122. package/translations/index.js +1 -1
  123. package/src/README.md +0 -27
  124. package/src/accessibility/index.js +0 -13
  125. package/src/app.js +0 -61
  126. package/src/color/index.js +0 -9
  127. package/src/color/p5.Color.culori.js +0 -66
  128. package/src/color/p5.Color.js +0 -851
  129. package/src/core/README.md +0 -91
  130. package/src/core/friendly_errors/index.js +0 -13
  131. package/src/core/friendly_errors/param_validator.js +0 -561
  132. package/src/core/init.js +0 -58
  133. package/src/core/internationalization.js +0 -195
  134. package/src/core/legacy.js +0 -29
  135. package/src/core/main.js +0 -689
  136. package/src/core/noop.js +0 -1
  137. package/src/core/p5.Graphics.js +0 -696
  138. package/src/core/p5.Renderer.js +0 -408
  139. package/src/core/reference.js +0 -2060
  140. package/src/core/rendering.js +0 -697
  141. package/src/dom/index.js +0 -11
  142. package/src/image/const.js +0 -6
  143. package/src/image/image.js +0 -731
  144. package/src/image/index.js +0 -15
  145. package/src/image/loading_displaying.js +0 -1431
  146. package/src/io/files.js +0 -2210
  147. package/src/io/index.js +0 -11
  148. package/src/math/README.md +0 -40
  149. package/src/type/index.js +0 -9
  150. package/src/webgl/3d_primitives.js +0 -2741
  151. package/src/webgl/index.js +0 -37
  152. package/src/webgl/light.js +0 -1851
  153. package/src/webgl/material.js +0 -3854
  154. package/src/webgl/p5.Camera.js +0 -4010
  155. package/src/webgl/p5.Framebuffer.js +0 -1865
  156. package/src/webgl/p5.RendererGL.js +0 -2867
  157. package/src/webgl/p5.Shader.js +0 -1505
  158. package/src/webgl/p5.Texture.js +0 -541
  159. package/src/webgl/shaders/basic.frag +0 -6
  160. package/src/webgl/shaders/filters/base.frag +0 -22
  161. package/src/webgl/shaders/filters/base.vert +0 -19
  162. package/src/webgl/shaders/filters/blur.frag +0 -60
  163. package/src/webgl/shaders/filters/default.vert +0 -18
  164. package/src/webgl/shaders/filters/dilate.frag +0 -39
  165. package/src/webgl/shaders/filters/erode.frag +0 -39
  166. package/src/webgl/shaders/filters/gray.frag +0 -16
  167. package/src/webgl/shaders/filters/invert.frag +0 -15
  168. package/src/webgl/shaders/filters/opaque.frag +0 -12
  169. package/src/webgl/shaders/filters/posterize.frag +0 -29
  170. package/src/webgl/shaders/filters/threshold.frag +0 -23
  171. package/src/webgl/shaders/font.frag +0 -216
  172. package/src/webgl/shaders/font.vert +0 -44
  173. package/src/webgl/shaders/imageLight.vert +0 -33
  174. package/src/webgl/shaders/imageLightDiffused.frag +0 -82
  175. package/src/webgl/shaders/imageLightSpecular.frag +0 -134
  176. package/src/webgl/shaders/light.vert +0 -37
  177. package/src/webgl/shaders/light_texture.frag +0 -26
  178. package/src/webgl/shaders/lighting.glsl +0 -227
  179. package/src/webgl/shaders/line.frag +0 -74
  180. package/src/webgl/shaders/line.vert +0 -294
  181. package/src/webgl/shaders/normal.frag +0 -6
  182. package/src/webgl/shaders/normal.vert +0 -72
  183. package/src/webgl/shaders/phong.frag +0 -84
  184. package/src/webgl/shaders/phong.vert +0 -87
  185. package/src/webgl/shaders/point.frag +0 -29
  186. package/src/webgl/shaders/point.vert +0 -19
  187. package/src/webgl/shaders/sphereMapping.frag +0 -26
  188. package/src/webgl/shaders/webgl2Compatibility.glsl +0 -34
@@ -1,1505 +0,0 @@
1
- /**
2
- * This module defines the p5.Shader class
3
- * @module 3D
4
- * @submodule Material
5
- * @for p5
6
- * @requires core
7
- */
8
-
9
- import { Texture } from './p5.Texture';
10
-
11
- class Shader {
12
- constructor(renderer, vertSrc, fragSrc, options = {}) {
13
- // TODO: adapt this to not take ids, but rather,
14
- // to take the source for a vertex and fragment shader
15
- // to enable custom shaders at some later date
16
- this._renderer = renderer;
17
- this._vertSrc = vertSrc;
18
- this._fragSrc = fragSrc;
19
- this._vertShader = -1;
20
- this._fragShader = -1;
21
- this._glProgram = 0;
22
- this._loadedAttributes = false;
23
- this.attributes = {};
24
- this._loadedUniforms = false;
25
- this.uniforms = {};
26
- this._bound = false;
27
- this.samplers = [];
28
- this.hooks = {
29
- // These should be passed in by `.modify()` instead of being manually
30
- // passed in.
31
-
32
- // Stores uniforms + default values.
33
- uniforms: options.uniforms || {},
34
-
35
- // Stores custom uniform + helper declarations as a string.
36
- declarations: options.declarations,
37
-
38
- // Stores helper functions to prepend to shaders.
39
- helpers: options.helpers || {},
40
-
41
- // Stores the hook implementations
42
- vertex: options.vertex || {},
43
- fragment: options.fragment || {},
44
-
45
- // Stores whether or not the hook implementation has been modified
46
- // from the default. This is supplied automatically by calling
47
- // yourShader.modify(...).
48
- modified: {
49
- vertex: (options.modified && options.modified.vertex) || {},
50
- fragment: (options.modified && options.modified.fragment) || {}
51
- }
52
- };
53
- }
54
-
55
- hookTypes(hookName) {
56
- let fullSrc = this._vertSrc;
57
- let body = this.hooks.vertex[hookName];
58
- if (!body) {
59
- body = this.hooks.fragment[hookName];
60
- fullSrc = this._fragSrc;
61
- }
62
- if (!body) {
63
- throw new Error(`Can't find hook ${hookName}!`);
64
- }
65
- const nameParts = hookName.split(/\s+/g);
66
- const functionName = nameParts.pop();
67
- const returnType = nameParts.pop();
68
- const returnQualifiers = [...nameParts];
69
-
70
- const parameterMatch = /\(([^\)]*)\)/.exec(body);
71
- if (!parameterMatch) {
72
- throw new Error(`Couldn't find function parameters in hook body:\n${body}`);
73
- }
74
-
75
- const structProperties = structName => {
76
- const structDefMatch = new RegExp(`struct\\s+${structName}\\s*\{([^\}]*)\}`).exec(fullSrc);
77
- if (!structDefMatch) return undefined;
78
-
79
- const properties = [];
80
- for (const defSrc of structDefMatch[1].split(';')) {
81
- // E.g. `int var1, var2;` or `MyStruct prop;`
82
- const parts = defSrc.trim().split(/\s+|,/g);
83
- const typeName = parts.shift();
84
- const names = [...parts];
85
- const typeProperties = structProperties(typeName);
86
- for (const name of names) {
87
- properties.push({
88
- name,
89
- type: {
90
- typeName,
91
- qualifiers: [],
92
- properties: typeProperties,
93
- },
94
- });
95
- }
96
- }
97
- return properties;
98
- };
99
-
100
- const parameters = parameterMatch[1].split(',').map(paramString => {
101
- // e.g. `int prop` or `in sampler2D prop` or `const float prop`
102
- const parts = paramString.trim().split(/\s+/g);
103
- const name = parts.pop();
104
- const typeName = parts.pop();
105
- const qualifiers = [...parts];
106
- const properties = structProperties(typeName);
107
- return {
108
- name,
109
- type: {
110
- typeName,
111
- qualifiers,
112
- properties,
113
- }
114
- }
115
- });
116
-
117
- return {
118
- name: functionName,
119
- returnType: {
120
- typeName: returnType,
121
- qualifiers: returnQualifiers,
122
- properties: structProperties(returnType)
123
- },
124
- parameters
125
- };
126
- }
127
-
128
- shaderSrc(src, shaderType) {
129
- const main = 'void main';
130
- let [preMain, postMain] = src.split(main);
131
-
132
- let hooks = '';
133
- let defines = '';
134
- for (const key in this.hooks.uniforms) {
135
- hooks += `uniform ${key};\n`;
136
- }
137
- if (this.hooks.declarations) {
138
- hooks += this.hooks.declarations + '\n';
139
- }
140
- if (this.hooks[shaderType].declarations) {
141
- hooks += this.hooks[shaderType].declarations + '\n';
142
- }
143
- for (const hookDef in this.hooks.helpers) {
144
- hooks += `${hookDef}${this.hooks.helpers[hookDef]}\n`;
145
- }
146
- for (const hookDef in this.hooks[shaderType]) {
147
- if (hookDef === 'declarations') continue;
148
- const [hookType, hookName] = hookDef.split(' ');
149
-
150
- // Add a #define so that if the shader wants to use preprocessor directives to
151
- // optimize away the extra function calls in main, it can do so
152
- if (this.hooks.modified[shaderType][hookDef]) {
153
- defines += '#define AUGMENTED_HOOK_' + hookName + '\n';
154
- }
155
-
156
- hooks +=
157
- hookType + ' HOOK_' + hookName + this.hooks[shaderType][hookDef] + '\n';
158
- }
159
-
160
- // Allow shaders to specify the location of hook #define statements. Normally these
161
- // go after function definitions, but one might want to have them defined earlier
162
- // in order to only conditionally make uniforms.
163
- if (preMain.indexOf('#define HOOK_DEFINES') !== -1) {
164
- preMain = preMain.replace('#define HOOK_DEFINES', '\n' + defines + '\n');
165
- defines = '';
166
- }
167
-
168
- return preMain + '\n' + defines + hooks + main + postMain;
169
- }
170
-
171
- /**
172
- * Shaders are written in <a href="https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_on_the_web/GLSL_Shaders">GLSL</a>, but
173
- * there are different versions of GLSL that it might be written in.
174
- *
175
- * Calling this method on a `p5.Shader` will return the GLSL version it uses, either `100 es` or `300 es`.
176
- * WebGL 1 shaders will only use `100 es`, and WebGL 2 shaders may use either.
177
- *
178
- * @returns {String} The GLSL version used by the shader.
179
- */
180
- version() {
181
- const match = /#version (.+)$/.exec(this.vertSrc());
182
- if (match) {
183
- return match[1];
184
- } else {
185
- return '100 es';
186
- }
187
- }
188
-
189
- vertSrc() {
190
- return this.shaderSrc(this._vertSrc, 'vertex');
191
- }
192
-
193
- fragSrc() {
194
- return this.shaderSrc(this._fragSrc, 'fragment');
195
- }
196
-
197
- /**
198
- * Logs the hooks available in this shader, and their current implementation.
199
- *
200
- * Each shader may let you override bits of its behavior. Each bit is called
201
- * a *hook.* A hook is either for the *vertex* shader, if it affects the
202
- * position of vertices, or in the *fragment* shader, if it affects the pixel
203
- * color. This method logs those values to the console, letting you know what
204
- * you are able to use in a call to
205
- * <a href="#/p5.Shader/modify">`modify()`</a>.
206
- *
207
- * For example, this shader will produce the following output:
208
- *
209
- * ```js
210
- * myShader = baseMaterialShader().modify({
211
- * declarations: 'uniform float time;',
212
- * 'vec3 getWorldPosition': `(vec3 pos) {
213
- * pos.y += 20. * sin(time * 0.001 + pos.x * 0.05);
214
- * return pos;
215
- * }`
216
- * });
217
- * myShader.inspectHooks();
218
- * ```
219
- *
220
- * ```
221
- * ==== Vertex shader hooks: ====
222
- * void beforeVertex() {}
223
- * vec3 getLocalPosition(vec3 position) { return position; }
224
- * [MODIFIED] vec3 getWorldPosition(vec3 pos) {
225
- * pos.y += 20. * sin(time * 0.001 + pos.x * 0.05);
226
- * return pos;
227
- * }
228
- * vec3 getLocalNormal(vec3 normal) { return normal; }
229
- * vec3 getWorldNormal(vec3 normal) { return normal; }
230
- * vec2 getUV(vec2 uv) { return uv; }
231
- * vec4 getVertexColor(vec4 color) { return color; }
232
- * void afterVertex() {}
233
- *
234
- * ==== Fragment shader hooks: ====
235
- * void beforeFragment() {}
236
- * Inputs getPixelInputs(Inputs inputs) { return inputs; }
237
- * vec4 combineColors(ColorComponents components) {
238
- * vec4 color = vec4(0.);
239
- * color.rgb += components.diffuse * components.baseColor;
240
- * color.rgb += components.ambient * components.ambientColor;
241
- * color.rgb += components.specular * components.specularColor;
242
- * color.rgb += components.emissive;
243
- * color.a = components.opacity;
244
- * return color;
245
- * }
246
- * vec4 getFinalColor(vec4 color) { return color; }
247
- * void afterFragment() {}
248
- * ```
249
- *
250
- * @beta
251
- */
252
- inspectHooks() {
253
- console.log('==== Vertex shader hooks: ====');
254
- for (const key in this.hooks.vertex) {
255
- console.log(
256
- (this.hooks.modified.vertex[key] ? '[MODIFIED] ' : '') +
257
- key +
258
- this.hooks.vertex[key]
259
- );
260
- }
261
- console.log('');
262
- console.log('==== Fragment shader hooks: ====');
263
- for (const key in this.hooks.fragment) {
264
- console.log(
265
- (this.hooks.modified.fragment[key] ? '[MODIFIED] ' : '') +
266
- key +
267
- this.hooks.fragment[key]
268
- );
269
- }
270
- console.log('');
271
- console.log('==== Helper functions: ====');
272
- for (const key in this.hooks.helpers) {
273
- console.log(key + this.hooks.helpers[key]);
274
- }
275
- }
276
-
277
- /**
278
- * Returns a new shader, based on the original, but with custom snippets
279
- * of shader code replacing default behaviour.
280
- *
281
- * Each shader may let you override bits of its behavior. Each bit is called
282
- * a *hook.* A hook is either for the *vertex* shader, if it affects the
283
- * position of vertices, or in the *fragment* shader, if it affects the pixel
284
- * color. You can inspect the different hooks available by calling
285
- * <a href="#/p5.Shader/inspectHooks">`yourShader.inspectHooks()`</a>. You can
286
- * also read the reference for the default material, normal material, color, line, and point shaders to
287
- * see what hooks they have available.
288
- *
289
- * `modify()` takes one parameter, `hooks`, an object with the hooks you want
290
- * to override. Each key of the `hooks` object is the name
291
- * of a hook, and the value is a string with the GLSL code for your hook.
292
- *
293
- * If you supply functions that aren't existing hooks, they will get added at the start of
294
- * the shader as helper functions so that you can use them in your hooks.
295
- *
296
- * To add new <a href="#/p5.Shader/setUniform">uniforms</a> to your shader, you can pass in a `uniforms` object containing
297
- * the type and name of the uniform as the key, and a default value or function returning
298
- * a default value as its value. These will be automatically set when the shader is set
299
- * with `shader(yourShader)`.
300
- *
301
- * You can also add a `declarations` key, where the value is a GLSL string declaring
302
- * custom uniform variables, globals, and functions shared
303
- * between hooks. To add declarations just in a vertex or fragment shader, add
304
- * `vertexDeclarations` and `fragmentDeclarations` keys.
305
- *
306
- * @beta
307
- * @param {Object} [hooks] The hooks in the shader to replace.
308
- * @returns {p5.Shader}
309
- *
310
- * @example
311
- * <div modernizr='webgl'>
312
- * <code>
313
- * let myShader;
314
- *
315
- * function setup() {
316
- * createCanvas(200, 200, WEBGL);
317
- * myShader = baseMaterialShader().modify({
318
- * uniforms: {
319
- * 'float time': () => millis() // Uniform for time
320
- * },
321
- * 'Vertex getWorldInputs': `(Vertex inputs) {
322
- * inputs.position.y +=
323
- * 20. * sin(time * 0.001 + inputs.position.x * 0.05);
324
- * return inputs;
325
- * }`
326
- * });
327
- * }
328
- *
329
- * function draw() {
330
- * background(255);
331
- * shader(myShader); // Apply the custom shader
332
- * lights(); // Enable lighting
333
- * noStroke(); // Disable stroke
334
- * fill('red'); // Set fill color to red
335
- * sphere(50); // Draw a sphere with the shader applied
336
- * }
337
- * </code>
338
- * </div>
339
- *
340
- * @example
341
- * <div modernizr='webgl'>
342
- * <code>
343
- * let myShader;
344
- *
345
- * function setup() {
346
- * createCanvas(200, 200, WEBGL);
347
- * myShader = baseMaterialShader().modify({
348
- * // Manually specifying a uniform
349
- * declarations: 'uniform float time;',
350
- * 'Vertex getWorldInputs': `(Vertex inputs) {
351
- * inputs.position.y +=
352
- * 20. * sin(time * 0.001 + inputs.position.x * 0.05);
353
- * return inputs;
354
- * }`
355
- * });
356
- * }
357
- *
358
- * function draw() {
359
- * background(255);
360
- * shader(myShader);
361
- * myShader.setUniform('time', millis());
362
- * lights();
363
- * noStroke();
364
- * fill('red');
365
- * sphere(50);
366
- * }
367
- * </code>
368
- * </div>
369
- */
370
- modify(hooks) {
371
- // p5._validateParameters('p5.Shader.modify', arguments);
372
- const newHooks = {
373
- vertex: {},
374
- fragment: {},
375
- helpers: {}
376
- };
377
- for (const key in hooks) {
378
- if (key === 'declarations') continue;
379
- if (key === 'uniforms') continue;
380
- if (key === 'vertexDeclarations') {
381
- newHooks.vertex.declarations =
382
- (newHooks.vertex.declarations || '') + '\n' + hooks[key];
383
- } else if (key === 'fragmentDeclarations') {
384
- newHooks.fragment.declarations =
385
- (newHooks.fragment.declarations || '') + '\n' + hooks[key];
386
- } else if (this.hooks.vertex[key]) {
387
- newHooks.vertex[key] = hooks[key];
388
- } else if (this.hooks.fragment[key]) {
389
- newHooks.fragment[key] = hooks[key];
390
- } else {
391
- newHooks.helpers[key] = hooks[key];
392
- }
393
- }
394
- const modifiedVertex = Object.assign({}, this.hooks.modified.vertex);
395
- const modifiedFragment = Object.assign({}, this.hooks.modified.fragment);
396
- for (const key in newHooks.vertex || {}) {
397
- if (key === 'declarations') continue;
398
- modifiedVertex[key] = true;
399
- }
400
- for (const key in newHooks.fragment || {}) {
401
- if (key === 'declarations') continue;
402
- modifiedFragment[key] = true;
403
- }
404
-
405
- return new Shader(this._renderer, this._vertSrc, this._fragSrc, {
406
- declarations:
407
- (this.hooks.declarations || '') + '\n' + (hooks.declarations || ''),
408
- uniforms: Object.assign({}, this.hooks.uniforms, hooks.uniforms || {}),
409
- fragment: Object.assign({}, this.hooks.fragment, newHooks.fragment || {}),
410
- vertex: Object.assign({}, this.hooks.vertex, newHooks.vertex || {}),
411
- helpers: Object.assign({}, this.hooks.helpers, newHooks.helpers || {}),
412
- modified: {
413
- vertex: modifiedVertex,
414
- fragment: modifiedFragment
415
- }
416
- });
417
- }
418
-
419
- /**
420
- * Creates, compiles, and links the shader based on its
421
- * sources for the vertex and fragment shaders (provided
422
- * to the constructor). Populates known attributes and
423
- * uniforms from the shader.
424
- * @chainable
425
- * @private
426
- */
427
- init() {
428
- if (this._glProgram === 0 /* or context is stale? */) {
429
- const gl = this._renderer.GL;
430
-
431
- // @todo: once custom shading is allowed,
432
- // friendly error messages should be used here to share
433
- // compiler and linker errors.
434
-
435
- //set up the shader by
436
- // 1. creating and getting a gl id for the shader program,
437
- // 2. compliling its vertex & fragment sources,
438
- // 3. linking the vertex and fragment shaders
439
- this._vertShader = gl.createShader(gl.VERTEX_SHADER);
440
- //load in our default vertex shader
441
- gl.shaderSource(this._vertShader, this.vertSrc());
442
- gl.compileShader(this._vertShader);
443
- // if our vertex shader failed compilation?
444
- if (!gl.getShaderParameter(this._vertShader, gl.COMPILE_STATUS)) {
445
- const glError = gl.getShaderInfoLog(this._vertShader);
446
- if (typeof IS_MINIFIED !== 'undefined') {
447
- console.error(glError);
448
- } else {
449
- throw glError;
450
- p5._friendlyError(
451
- `Yikes! An error occurred compiling the vertex shader:${glError}`
452
- );
453
- }
454
- return null;
455
- }
456
-
457
- this._fragShader = gl.createShader(gl.FRAGMENT_SHADER);
458
- //load in our material frag shader
459
- gl.shaderSource(this._fragShader, this.fragSrc());
460
- gl.compileShader(this._fragShader);
461
- // if our frag shader failed compilation?
462
- if (!gl.getShaderParameter(this._fragShader, gl.COMPILE_STATUS)) {
463
- const glError = gl.getShaderInfoLog(this._fragShader);
464
- if (typeof IS_MINIFIED !== 'undefined') {
465
- console.error(glError);
466
- } else {
467
- throw glError;
468
- p5._friendlyError(
469
- `Darn! An error occurred compiling the fragment shader:${glError}`
470
- );
471
- }
472
- return null;
473
- }
474
-
475
- this._glProgram = gl.createProgram();
476
- gl.attachShader(this._glProgram, this._vertShader);
477
- gl.attachShader(this._glProgram, this._fragShader);
478
- gl.linkProgram(this._glProgram);
479
- if (!gl.getProgramParameter(this._glProgram, gl.LINK_STATUS)) {
480
- p5._friendlyError(
481
- `Snap! Error linking shader program: ${gl.getProgramInfoLog(
482
- this._glProgram
483
- )}`
484
- );
485
- }
486
-
487
- this._loadAttributes();
488
- this._loadUniforms();
489
- }
490
- return this;
491
- }
492
-
493
- /**
494
- * @private
495
- */
496
- setDefaultUniforms() {
497
- for (const key in this.hooks.uniforms) {
498
- const [, name] = key.split(' ');
499
- const initializer = this.hooks.uniforms[key];
500
- let value;
501
- if (initializer instanceof Function) {
502
- value = initializer();
503
- } else {
504
- value = initializer;
505
- }
506
-
507
- if (value !== undefined && value !== null) {
508
- this.setUniform(name, value);
509
- }
510
- }
511
- }
512
-
513
- /**
514
- * Copies the shader from one drawing context to another.
515
- *
516
- * Each `p5.Shader` object must be compiled by calling
517
- * <a href="#/p5/shader">shader()</a> before it can run. Compilation happens
518
- * in a drawing context which is usually the main canvas or an instance of
519
- * <a href="#/p5.Graphics">p5.Graphics</a>. A shader can only be used in the
520
- * context where it was compiled. The `copyToContext()` method compiles the
521
- * shader again and copies it to another drawing context where it can be
522
- * reused.
523
- *
524
- * The parameter, `context`, is the drawing context where the shader will be
525
- * used. The shader can be copied to an instance of
526
- * <a href="#/p5.Graphics">p5.Graphics</a>, as in
527
- * `myShader.copyToContext(pg)`. The shader can also be copied from a
528
- * <a href="#/p5.Graphics">p5.Graphics</a> object to the main canvas using
529
- * the `p5.instance` variable, as in `myShader.copyToContext(p5.instance)`.
530
- *
531
- * Note: A <a href="#/p5.Shader">p5.Shader</a> object created with
532
- * <a href="#/p5/createShader">createShader()</a>,
533
- * <a href="#/p5/createFilterShader">createFilterShader()</a>, or
534
- * <a href="#/p5/loadShader">loadShader()</a>
535
- * can be used directly with a <a href="#/p5.Framebuffer">p5.Framebuffer</a>
536
- * object created with
537
- * <a href="#/p5/createFramebuffer">createFramebuffer()</a>. Both objects
538
- * have the same context as the main canvas.
539
- *
540
- * @param {p5|p5.Graphics} context WebGL context for the copied shader.
541
- * @returns {p5.Shader} new shader compiled for the target context.
542
- *
543
- * @example
544
- * <div>
545
- * <code>
546
- * // Note: A "uniform" is a global variable within a shader program.
547
- *
548
- * // Create a string with the vertex shader program.
549
- * // The vertex shader is called for each vertex.
550
- * let vertSrc = `
551
- * precision highp float;
552
- * uniform mat4 uModelViewMatrix;
553
- * uniform mat4 uProjectionMatrix;
554
- *
555
- * attribute vec3 aPosition;
556
- * attribute vec2 aTexCoord;
557
- * varying vec2 vTexCoord;
558
- *
559
- * void main() {
560
- * vTexCoord = aTexCoord;
561
- * vec4 positionVec4 = vec4(aPosition, 1.0);
562
- * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;
563
- * }
564
- * `;
565
- *
566
- * // Create a string with the fragment shader program.
567
- * // The fragment shader is called for each pixel.
568
- * let fragSrc = `
569
- * precision mediump float;
570
- * varying vec2 vTexCoord;
571
- *
572
- * void main() {
573
- * vec2 uv = vTexCoord;
574
- * vec3 color = vec3(uv.x, uv.y, min(uv.x + uv.y, 1.0));
575
- * gl_FragColor = vec4(color, 1.0);\
576
- * }
577
- * `;
578
- *
579
- * let pg;
580
- *
581
- * function setup() {
582
- * createCanvas(100, 100, WEBGL);
583
- *
584
- * background(200);
585
- *
586
- * // Create a p5.Shader object.
587
- * let original = createShader(vertSrc, fragSrc);
588
- *
589
- * // Compile the p5.Shader object.
590
- * shader(original);
591
- *
592
- * // Create a p5.Graphics object.
593
- * pg = createGraphics(50, 50, WEBGL);
594
- *
595
- * // Copy the original shader to the p5.Graphics object.
596
- * let copied = original.copyToContext(pg);
597
- *
598
- * // Apply the copied shader to the p5.Graphics object.
599
- * pg.shader(copied);
600
- *
601
- * // Style the display surface.
602
- * pg.noStroke();
603
- *
604
- * // Add a display surface for the shader.
605
- * pg.plane(50, 50);
606
- *
607
- * describe('A square with purple-blue gradient on its surface drawn against a gray background.');
608
- * }
609
- *
610
- * function draw() {
611
- * background(200);
612
- *
613
- * // Draw the p5.Graphics object to the main canvas.
614
- * image(pg, -25, -25);
615
- * }
616
- * </code>
617
- * </div>
618
- *
619
- * <div class='notest'>
620
- * <code>
621
- * // Note: A "uniform" is a global variable within a shader program.
622
- *
623
- * // Create a string with the vertex shader program.
624
- * // The vertex shader is called for each vertex.
625
- * let vertSrc = `
626
- * precision highp float;
627
- * uniform mat4 uModelViewMatrix;
628
- * uniform mat4 uProjectionMatrix;
629
- *
630
- * attribute vec3 aPosition;
631
- * attribute vec2 aTexCoord;
632
- * varying vec2 vTexCoord;
633
- *
634
- * void main() {
635
- * vTexCoord = aTexCoord;
636
- * vec4 positionVec4 = vec4(aPosition, 1.0);
637
- * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;
638
- * }
639
- * `;
640
- *
641
- * // Create a string with the fragment shader program.
642
- * // The fragment shader is called for each pixel.
643
- * let fragSrc = `
644
- * precision mediump float;
645
- *
646
- * varying vec2 vTexCoord;
647
- *
648
- * void main() {
649
- * vec2 uv = vTexCoord;
650
- * vec3 color = vec3(uv.x, uv.y, min(uv.x + uv.y, 1.0));
651
- * gl_FragColor = vec4(color, 1.0);
652
- * }
653
- * `;
654
- *
655
- * let copied;
656
- *
657
- * function setup() {
658
- * createCanvas(100, 100, WEBGL);
659
- *
660
- * // Create a p5.Graphics object.
661
- * let pg = createGraphics(25, 25, WEBGL);
662
- *
663
- * // Create a p5.Shader object.
664
- * let original = pg.createShader(vertSrc, fragSrc);
665
- *
666
- * // Compile the p5.Shader object.
667
- * pg.shader(original);
668
- *
669
- * // Copy the original shader to the main canvas.
670
- * copied = original.copyToContext(p5.instance);
671
- *
672
- * // Apply the copied shader to the main canvas.
673
- * shader(copied);
674
- *
675
- * describe('A rotating cube with a purple-blue gradient on its surface drawn against a gray background.');
676
- * }
677
- *
678
- * function draw() {
679
- * background(200);
680
- *
681
- * // Rotate around the x-, y-, and z-axes.
682
- * rotateX(frameCount * 0.01);
683
- * rotateY(frameCount * 0.01);
684
- * rotateZ(frameCount * 0.01);
685
- *
686
- * // Draw the box.
687
- * box(50);
688
- * }
689
- * </code>
690
- * </div>
691
- */
692
- copyToContext(context) {
693
- const shader = new Shader(
694
- context._renderer,
695
- this._vertSrc,
696
- this._fragSrc
697
- );
698
- shader.ensureCompiledOnContext(context._renderer);
699
- return shader;
700
- }
701
-
702
- /**
703
- * @private
704
- */
705
- ensureCompiledOnContext(context) {
706
- if (this._glProgram !== 0 && this._renderer !== context) {
707
- throw new Error(
708
- 'The shader being run is attached to a different context. Do you need to copy it to this context first with .copyToContext()?'
709
- );
710
- } else if (this._glProgram === 0) {
711
- this._renderer = context?._renderer?.filterRenderer?._renderer || context;
712
- this.init();
713
- }
714
- }
715
-
716
-
717
- /**
718
- * Queries the active attributes for this shader and loads
719
- * their names and locations into the attributes array.
720
- * @private
721
- */
722
- _loadAttributes() {
723
- if (this._loadedAttributes) {
724
- return;
725
- }
726
-
727
- this.attributes = {};
728
-
729
- const gl = this._renderer.GL;
730
-
731
- const numAttributes = gl.getProgramParameter(
732
- this._glProgram,
733
- gl.ACTIVE_ATTRIBUTES
734
- );
735
- for (let i = 0; i < numAttributes; ++i) {
736
- const attributeInfo = gl.getActiveAttrib(this._glProgram, i);
737
- const name = attributeInfo.name;
738
- const location = gl.getAttribLocation(this._glProgram, name);
739
- const attribute = {};
740
- attribute.name = name;
741
- attribute.location = location;
742
- attribute.index = i;
743
- attribute.type = attributeInfo.type;
744
- attribute.size = attributeInfo.size;
745
- this.attributes[name] = attribute;
746
- }
747
-
748
- this._loadedAttributes = true;
749
- }
750
-
751
- /**
752
- * Queries the active uniforms for this shader and loads
753
- * their names and locations into the uniforms array.
754
- * @private
755
- */
756
- _loadUniforms() {
757
- if (this._loadedUniforms) {
758
- return;
759
- }
760
-
761
- const gl = this._renderer.GL;
762
-
763
- // Inspect shader and cache uniform info
764
- const numUniforms = gl.getProgramParameter(
765
- this._glProgram,
766
- gl.ACTIVE_UNIFORMS
767
- );
768
-
769
- let samplerIndex = 0;
770
- for (let i = 0; i < numUniforms; ++i) {
771
- const uniformInfo = gl.getActiveUniform(this._glProgram, i);
772
- const uniform = {};
773
- uniform.location = gl.getUniformLocation(
774
- this._glProgram,
775
- uniformInfo.name
776
- );
777
- uniform.size = uniformInfo.size;
778
- let uniformName = uniformInfo.name;
779
- //uniforms that are arrays have their name returned as
780
- //someUniform[0] which is a bit silly so we trim it
781
- //off here. The size property tells us that its an array
782
- //so we dont lose any information by doing this
783
- if (uniformInfo.size > 1) {
784
- uniformName = uniformName.substring(0, uniformName.indexOf('[0]'));
785
- }
786
- uniform.name = uniformName;
787
- uniform.type = uniformInfo.type;
788
- uniform._cachedData = undefined;
789
- if (uniform.type === gl.SAMPLER_2D) {
790
- uniform.samplerIndex = samplerIndex;
791
- samplerIndex++;
792
- this.samplers.push(uniform);
793
- }
794
-
795
- uniform.isArray =
796
- uniformInfo.size > 1 ||
797
- uniform.type === gl.FLOAT_MAT3 ||
798
- uniform.type === gl.FLOAT_MAT4 ||
799
- uniform.type === gl.FLOAT_VEC2 ||
800
- uniform.type === gl.FLOAT_VEC3 ||
801
- uniform.type === gl.FLOAT_VEC4 ||
802
- uniform.type === gl.INT_VEC2 ||
803
- uniform.type === gl.INT_VEC4 ||
804
- uniform.type === gl.INT_VEC3;
805
-
806
- this.uniforms[uniformName] = uniform;
807
- }
808
- this._loadedUniforms = true;
809
- }
810
-
811
- compile() {
812
- // TODO
813
- }
814
-
815
- /**
816
- * initializes (if needed) and binds the shader program.
817
- * @private
818
- */
819
- bindShader() {
820
- this.init();
821
- if (!this._bound) {
822
- this.useProgram();
823
- this._bound = true;
824
- }
825
- }
826
-
827
- /**
828
- * @chainable
829
- * @private
830
- */
831
- unbindShader() {
832
- if (this._bound) {
833
- this.unbindTextures();
834
- this._bound = false;
835
- }
836
- return this;
837
- }
838
-
839
- bindTextures() {
840
- const gl = this._renderer.GL;
841
-
842
- const empty = this._renderer._getEmptyTexture();
843
-
844
- for (const uniform of this.samplers) {
845
- let tex = uniform.texture;
846
- if (
847
- tex === undefined ||
848
- (
849
- false &&
850
- tex.isFramebufferTexture &&
851
- !tex.src.framebuffer.antialias &&
852
- tex.src.framebuffer === this._renderer.activeFramebuffer()
853
- )
854
- ) {
855
- // user hasn't yet supplied a texture for this slot.
856
- // (or there may not be one--maybe just lighting),
857
- // so we supply a default texture instead.
858
- uniform.texture = tex = empty;
859
- }
860
- gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex);
861
- tex.bindTexture();
862
- tex.update();
863
- gl.uniform1i(uniform.location, uniform.samplerIndex);
864
- }
865
- }
866
-
867
- updateTextures() {
868
- for (const uniform of this.samplers) {
869
- const tex = uniform.texture;
870
- if (tex) {
871
- tex.update();
872
- }
873
- }
874
- }
875
-
876
- unbindTextures() {
877
- const gl = this._renderer.GL;
878
- const empty = this._renderer._getEmptyTexture();
879
- for (const uniform of this.samplers) {
880
- if (uniform.texture?.isFramebufferTexture) {
881
- gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex);
882
- empty.bindTexture();
883
- gl.uniform1i(uniform.location, uniform.samplerIndex);
884
- }
885
- }
886
- }
887
-
888
- /**
889
- * @chainable
890
- * @private
891
- */
892
- useProgram() {
893
- const gl = this._renderer.GL;
894
- if (this._renderer._curShader !== this) {
895
- gl.useProgram(this._glProgram);
896
- this._renderer._curShader = this;
897
- }
898
- return this;
899
- }
900
-
901
- /**
902
- * Sets the shader’s uniform (global) variables.
903
- *
904
- * Shader programs run on the computer’s graphics processing unit (GPU).
905
- * They live in part of the computer’s memory that’s completely separate
906
- * from the sketch that runs them. Uniforms are global variables within a
907
- * shader program. They provide a way to pass values from a sketch running
908
- * on the CPU to a shader program running on the GPU.
909
- *
910
- * The first parameter, `uniformName`, is a string with the uniform’s name.
911
- * For the shader above, `uniformName` would be `'r'`.
912
- *
913
- * The second parameter, `data`, is the value that should be used to set the
914
- * uniform. For example, calling `myShader.setUniform('r', 0.5)` would set
915
- * the `r` uniform in the shader above to `0.5`. data should match the
916
- * uniform’s type. Numbers, strings, booleans, arrays, and many types of
917
- * images can all be passed to a shader with `setUniform()`.
918
- *
919
- * @chainable
920
- * @param {String} uniformName name of the uniform. Must match the name
921
- * used in the vertex and fragment shaders.
922
- * @param {Boolean|Number|Number[]|p5.Image|p5.Graphics|p5.MediaElement|p5.Texture}
923
- * data value to assign to the uniform. Must match the uniform’s data type.
924
- *
925
- * @example
926
- * <div>
927
- * <code>
928
- * // Note: A "uniform" is a global variable within a shader program.
929
- *
930
- * // Create a string with the vertex shader program.
931
- * // The vertex shader is called for each vertex.
932
- * let vertSrc = `
933
- * precision highp float;
934
- * uniform mat4 uModelViewMatrix;
935
- * uniform mat4 uProjectionMatrix;
936
- *
937
- * attribute vec3 aPosition;
938
- * attribute vec2 aTexCoord;
939
- * varying vec2 vTexCoord;
940
- *
941
- * void main() {
942
- * vTexCoord = aTexCoord;
943
- * vec4 positionVec4 = vec4(aPosition, 1.0);
944
- * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;
945
- * }
946
- * `;
947
- *
948
- * // Create a string with the fragment shader program.
949
- * // The fragment shader is called for each pixel.
950
- * let fragSrc = `
951
- * precision mediump float;
952
- *
953
- * uniform float r;
954
- *
955
- * void main() {
956
- * gl_FragColor = vec4(r, 1.0, 1.0, 1.0);
957
- * }
958
- * `;
959
- *
960
- * function setup() {
961
- * createCanvas(100, 100, WEBGL);
962
- *
963
- * // Create a p5.Shader object.
964
- * let myShader = createShader(vertSrc, fragSrc);
965
- *
966
- * // Apply the p5.Shader object.
967
- * shader(myShader);
968
- *
969
- * // Set the r uniform to 0.5.
970
- * myShader.setUniform('r', 0.5);
971
- *
972
- * // Style the drawing surface.
973
- * noStroke();
974
- *
975
- * // Add a plane as a drawing surface for the shader.
976
- * plane(100, 100);
977
- *
978
- * describe('A cyan square.');
979
- * }
980
- * </code>
981
- * </div>
982
- *
983
- * <div>
984
- * <code>
985
- * // Note: A "uniform" is a global variable within a shader program.
986
- *
987
- * // Create a string with the vertex shader program.
988
- * // The vertex shader is called for each vertex.
989
- * let vertSrc = `
990
- * precision highp float;
991
- * uniform mat4 uModelViewMatrix;
992
- * uniform mat4 uProjectionMatrix;
993
- *
994
- * attribute vec3 aPosition;
995
- * attribute vec2 aTexCoord;
996
- * varying vec2 vTexCoord;
997
- *
998
- * void main() {
999
- * vTexCoord = aTexCoord;
1000
- * vec4 positionVec4 = vec4(aPosition, 1.0);
1001
- * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;
1002
- * }
1003
- * `;
1004
- *
1005
- * // Create a string with the fragment shader program.
1006
- * // The fragment shader is called for each pixel.
1007
- * let fragSrc = `
1008
- * precision mediump float;
1009
- *
1010
- * uniform float r;
1011
- *
1012
- * void main() {
1013
- * gl_FragColor = vec4(r, 1.0, 1.0, 1.0);
1014
- * }
1015
- * `;
1016
- *
1017
- * let myShader;
1018
- *
1019
- * function setup() {
1020
- * createCanvas(100, 100, WEBGL);
1021
- *
1022
- * // Create a p5.Shader object.
1023
- * myShader = createShader(vertSrc, fragSrc);
1024
- *
1025
- * // Compile and apply the p5.Shader object.
1026
- * shader(myShader);
1027
- *
1028
- * describe('A square oscillates color between cyan and white.');
1029
- * }
1030
- *
1031
- * function draw() {
1032
- * background(200);
1033
- *
1034
- * // Style the drawing surface.
1035
- * noStroke();
1036
- *
1037
- * // Update the r uniform.
1038
- * let nextR = 0.5 * (sin(frameCount * 0.01) + 1);
1039
- * myShader.setUniform('r', nextR);
1040
- *
1041
- * // Add a plane as a drawing surface.
1042
- * plane(100, 100);
1043
- * }
1044
- * </code>
1045
- * </div>
1046
- *
1047
- * <div>
1048
- * <code>
1049
- * // Note: A "uniform" is a global variable within a shader program.
1050
- *
1051
- * // Create a string with the vertex shader program.
1052
- * // The vertex shader is called for each vertex.
1053
- * let vertSrc = `
1054
- * precision highp float;
1055
- * uniform mat4 uModelViewMatrix;
1056
- * uniform mat4 uProjectionMatrix;
1057
- *
1058
- * attribute vec3 aPosition;
1059
- * attribute vec2 aTexCoord;
1060
- * varying vec2 vTexCoord;
1061
- *
1062
- * void main() {
1063
- * vTexCoord = aTexCoord;
1064
- * vec4 positionVec4 = vec4(aPosition, 1.0);
1065
- * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;
1066
- * }
1067
- * `;
1068
- *
1069
- * // Create a string with the fragment shader program.
1070
- * // The fragment shader is called for each pixel.
1071
- * let fragSrc = `
1072
- * precision highp float;
1073
- * uniform vec2 p;
1074
- * uniform float r;
1075
- * const int numIterations = 500;
1076
- * varying vec2 vTexCoord;
1077
- *
1078
- * void main() {
1079
- * vec2 c = p + gl_FragCoord.xy * r;
1080
- * vec2 z = c;
1081
- * float n = 0.0;
1082
- *
1083
- * for (int i = numIterations; i > 0; i--) {
1084
- * if (z.x * z.x + z.y * z.y > 4.0) {
1085
- * n = float(i) / float(numIterations);
1086
- * break;
1087
- * }
1088
- *
1089
- * z = vec2(z.x * z.x - z.y * z.y, 2.0 * z.x * z.y) + c;
1090
- * }
1091
- *
1092
- * gl_FragColor = vec4(
1093
- * 0.5 - cos(n * 17.0) / 2.0,
1094
- * 0.5 - cos(n * 13.0) / 2.0,
1095
- * 0.5 - cos(n * 23.0) / 2.0,
1096
- * 1.0
1097
- * );
1098
- * }
1099
- * `;
1100
- *
1101
- * let mandelbrot;
1102
- *
1103
- * function setup() {
1104
- * createCanvas(100, 100, WEBGL);
1105
- *
1106
- * // Create a p5.Shader object.
1107
- * mandelbrot = createShader(vertSrc, fragSrc);
1108
- *
1109
- * // Compile and apply the p5.Shader object.
1110
- * shader(mandelbrot);
1111
- *
1112
- * // Set the shader uniform p to an array.
1113
- * // p is the center point of the Mandelbrot image.
1114
- * mandelbrot.setUniform('p', [-0.74364388703, 0.13182590421]);
1115
- *
1116
- * describe('A fractal image zooms in and out of focus.');
1117
- * }
1118
- *
1119
- * function draw() {
1120
- * // Set the shader uniform r to a value that oscillates
1121
- * // between 0 and 0.005.
1122
- * // r is the size of the image in Mandelbrot-space.
1123
- * let radius = 0.005 * (sin(frameCount * 0.01) + 1);
1124
- * mandelbrot.setUniform('r', radius);
1125
- *
1126
- * // Style the drawing surface.
1127
- * noStroke();
1128
- *
1129
- * // Add a plane as a drawing surface.
1130
- * plane(100, 100);
1131
- * }
1132
- * </code>
1133
- * </div>
1134
- */
1135
- setUniform(uniformName, data) {
1136
- this.init();
1137
-
1138
- const uniform = this.uniforms[uniformName];
1139
- if (!uniform) {
1140
- return;
1141
- }
1142
- const gl = this._renderer.GL;
1143
-
1144
- if (uniform.isArray) {
1145
- if (
1146
- uniform._cachedData &&
1147
- this._renderer._arraysEqual(uniform._cachedData, data)
1148
- ) {
1149
- return;
1150
- } else {
1151
- uniform._cachedData = data.slice(0);
1152
- }
1153
- } else if (uniform._cachedData && uniform._cachedData === data) {
1154
- return;
1155
- } else {
1156
- if (Array.isArray(data)) {
1157
- uniform._cachedData = data.slice(0);
1158
- } else {
1159
- uniform._cachedData = data;
1160
- }
1161
- }
1162
-
1163
- const location = uniform.location;
1164
-
1165
- this.useProgram();
1166
-
1167
- switch (uniform.type) {
1168
- case gl.BOOL:
1169
- if (data === true) {
1170
- gl.uniform1i(location, 1);
1171
- } else {
1172
- gl.uniform1i(location, 0);
1173
- }
1174
- break;
1175
- case gl.INT:
1176
- if (uniform.size > 1) {
1177
- data.length && gl.uniform1iv(location, data);
1178
- } else {
1179
- gl.uniform1i(location, data);
1180
- }
1181
- break;
1182
- case gl.FLOAT:
1183
- if (uniform.size > 1) {
1184
- data.length && gl.uniform1fv(location, data);
1185
- } else {
1186
- gl.uniform1f(location, data);
1187
- }
1188
- break;
1189
- case gl.FLOAT_MAT3:
1190
- gl.uniformMatrix3fv(location, false, data);
1191
- break;
1192
- case gl.FLOAT_MAT4:
1193
- gl.uniformMatrix4fv(location, false, data);
1194
- break;
1195
- case gl.FLOAT_VEC2:
1196
- if (uniform.size > 1) {
1197
- data.length && gl.uniform2fv(location, data);
1198
- } else {
1199
- gl.uniform2f(location, data[0], data[1]);
1200
- }
1201
- break;
1202
- case gl.FLOAT_VEC3:
1203
- if (uniform.size > 1) {
1204
- data.length && gl.uniform3fv(location, data);
1205
- } else {
1206
- gl.uniform3f(location, data[0], data[1], data[2]);
1207
- }
1208
- break;
1209
- case gl.FLOAT_VEC4:
1210
- if (uniform.size > 1) {
1211
- data.length && gl.uniform4fv(location, data);
1212
- } else {
1213
- gl.uniform4f(location, data[0], data[1], data[2], data[3]);
1214
- }
1215
- break;
1216
- case gl.INT_VEC2:
1217
- if (uniform.size > 1) {
1218
- data.length && gl.uniform2iv(location, data);
1219
- } else {
1220
- gl.uniform2i(location, data[0], data[1]);
1221
- }
1222
- break;
1223
- case gl.INT_VEC3:
1224
- if (uniform.size > 1) {
1225
- data.length && gl.uniform3iv(location, data);
1226
- } else {
1227
- gl.uniform3i(location, data[0], data[1], data[2]);
1228
- }
1229
- break;
1230
- case gl.INT_VEC4:
1231
- if (uniform.size > 1) {
1232
- data.length && gl.uniform4iv(location, data);
1233
- } else {
1234
- gl.uniform4i(location, data[0], data[1], data[2], data[3]);
1235
- }
1236
- break;
1237
- case gl.SAMPLER_2D:
1238
- if (typeof data == 'number') {
1239
- if (
1240
- data < gl.TEXTURE0 ||
1241
- data > gl.TEXTURE31 ||
1242
- data !== Math.ceil(data)
1243
- ) {
1244
- console.log(
1245
- '🌸 p5.js says: ' +
1246
- "You're trying to use a number as the data for a texture." +
1247
- 'Please use a texture.'
1248
- );
1249
- return this;
1250
- }
1251
- gl.activeTexture(data);
1252
- gl.uniform1i(location, data);
1253
- } else {
1254
- gl.activeTexture(gl.TEXTURE0 + uniform.samplerIndex);
1255
- uniform.texture =
1256
- data instanceof Texture ? data : this._renderer.getTexture(data);
1257
- gl.uniform1i(location, uniform.samplerIndex);
1258
- if (uniform.texture.src.gifProperties) {
1259
- uniform.texture.src._animateGif(this._renderer._pInst);
1260
- }
1261
- }
1262
- break;
1263
- case gl.SAMPLER_CUBE:
1264
- case gl.SAMPLER_3D:
1265
- case gl.SAMPLER_2D_SHADOW:
1266
- case gl.SAMPLER_2D_ARRAY:
1267
- case gl.SAMPLER_2D_ARRAY_SHADOW:
1268
- case gl.SAMPLER_CUBE_SHADOW:
1269
- case gl.INT_SAMPLER_2D:
1270
- case gl.INT_SAMPLER_3D:
1271
- case gl.INT_SAMPLER_CUBE:
1272
- case gl.INT_SAMPLER_2D_ARRAY:
1273
- case gl.UNSIGNED_INT_SAMPLER_2D:
1274
- case gl.UNSIGNED_INT_SAMPLER_3D:
1275
- case gl.UNSIGNED_INT_SAMPLER_CUBE:
1276
- case gl.UNSIGNED_INT_SAMPLER_2D_ARRAY:
1277
- if (typeof data !== 'number') {
1278
- break;
1279
- }
1280
- if (
1281
- data < gl.TEXTURE0 ||
1282
- data > gl.TEXTURE31 ||
1283
- data !== Math.ceil(data)
1284
- ) {
1285
- console.log(
1286
- '🌸 p5.js says: ' +
1287
- "You're trying to use a number as the data for a texture." +
1288
- 'Please use a texture.'
1289
- );
1290
- break;
1291
- }
1292
- gl.activeTexture(data);
1293
- gl.uniform1i(location, data);
1294
- break;
1295
- //@todo complete all types
1296
- }
1297
- return this;
1298
- }
1299
-
1300
- /**
1301
- * @chainable
1302
- * @private
1303
- */
1304
- enableAttrib(attr, size, type, normalized, stride, offset) {
1305
- if (attr) {
1306
- if (
1307
- typeof IS_MINIFIED === 'undefined' &&
1308
- this.attributes[attr.name] !== attr
1309
- ) {
1310
- console.warn(
1311
- `The attribute "${attr.name}"passed to enableAttrib does not belong to this shader.`
1312
- );
1313
- }
1314
- const loc = attr.location;
1315
- if (loc !== -1) {
1316
- const gl = this._renderer.GL;
1317
- // Enable register even if it is disabled
1318
- if (!this._renderer.registerEnabled.has(loc)) {
1319
- gl.enableVertexAttribArray(loc);
1320
- // Record register availability
1321
- this._renderer.registerEnabled.add(loc);
1322
- }
1323
- this._renderer.GL.vertexAttribPointer(
1324
- loc,
1325
- size,
1326
- type || gl.FLOAT,
1327
- normalized || false,
1328
- stride || 0,
1329
- offset || 0
1330
- );
1331
- }
1332
- }
1333
- return this;
1334
- }
1335
-
1336
- /**
1337
- * Once all buffers have been bound, this checks to see if there are any
1338
- * remaining active attributes, likely left over from previous renders,
1339
- * and disables them so that they don't affect rendering.
1340
- * @private
1341
- */
1342
- disableRemainingAttributes() {
1343
- for (const location of this._renderer.registerEnabled.values()) {
1344
- if (
1345
- !Object.keys(this.attributes).some(
1346
- key => this.attributes[key].location === location
1347
- )
1348
- ) {
1349
- this._renderer.GL.disableVertexAttribArray(location);
1350
- this._renderer.registerEnabled.delete(location);
1351
- }
1352
- }
1353
- }
1354
- };
1355
-
1356
- function shader(p5, fn){
1357
- /**
1358
- * A class to describe a shader program.
1359
- *
1360
- * Each `p5.Shader` object contains a shader program that runs on the graphics
1361
- * processing unit (GPU). Shaders can process many pixels or vertices at the
1362
- * same time, making them fast for many graphics tasks. They’re written in a
1363
- * language called
1364
- * <a href="https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_on_the_web/GLSL_Shaders" target="_blank">GLSL</a>
1365
- * and run along with the rest of the code in a sketch.
1366
- *
1367
- * A shader program consists of two files, a vertex shader and a fragment
1368
- * shader. The vertex shader affects where 3D geometry is drawn on the screen
1369
- * and the fragment shader affects color. Once the `p5.Shader` object is
1370
- * created, it can be used with the <a href="#/p5/shader">shader()</a>
1371
- * function, as in `shader(myShader)`.
1372
- *
1373
- * A shader can optionally describe *hooks,* which are functions in GLSL that
1374
- * users may choose to provide to customize the behavior of the shader. For the
1375
- * vertex or the fragment shader, users can pass in an object where each key is
1376
- * the type and name of a hook function, and each value is a string with the
1377
- * parameter list and default implementation of the hook. For example, to let users
1378
- * optionally run code at the start of the vertex shader, the options object could
1379
- * include:
1380
- *
1381
- * ```js
1382
- * {
1383
- * vertex: {
1384
- * 'void beforeVertex': '() {}'
1385
- * }
1386
- * }
1387
- * ```
1388
- *
1389
- * Then, in your vertex shader source, you can run a hook by calling a function
1390
- * with the same name prefixed by `HOOK_`:
1391
- *
1392
- * ```glsl
1393
- * void main() {
1394
- * HOOK_beforeVertex();
1395
- * // Add the rest ofy our shader code here!
1396
- * }
1397
- * ```
1398
- *
1399
- * Note: <a href="#/p5/createShader">createShader()</a>,
1400
- * <a href="#/p5/createFilterShader">createFilterShader()</a>, and
1401
- * <a href="#/p5/loadShader">loadShader()</a> are the recommended ways to
1402
- * create an instance of this class.
1403
- *
1404
- * @class p5.Shader
1405
- * @constructor
1406
- * @param {p5.RendererGL} renderer WebGL context for this shader.
1407
- * @param {String} vertSrc source code for the vertex shader program.
1408
- * @param {String} fragSrc source code for the fragment shader program.
1409
- * @param {Object} [options] An optional object describing how this shader can
1410
- * be augmented with hooks. It can include:
1411
- * - `vertex`: An object describing the available vertex shader hooks.
1412
- * - `fragment`: An object describing the available frament shader hooks.
1413
- *
1414
- * @example
1415
- * <div>
1416
- * <code>
1417
- * // Note: A "uniform" is a global variable within a shader program.
1418
- *
1419
- * // Create a string with the vertex shader program.
1420
- * // The vertex shader is called for each vertex.
1421
- * let vertSrc = `
1422
- * precision highp float;
1423
- * uniform mat4 uModelViewMatrix;
1424
- * uniform mat4 uProjectionMatrix;
1425
- *
1426
- * attribute vec3 aPosition;
1427
- * attribute vec2 aTexCoord;
1428
- * varying vec2 vTexCoord;
1429
- *
1430
- * void main() {
1431
- * vTexCoord = aTexCoord;
1432
- * vec4 positionVec4 = vec4(aPosition, 1.0);
1433
- * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;
1434
- * }
1435
- * `;
1436
- *
1437
- * // Create a string with the fragment shader program.
1438
- * // The fragment shader is called for each pixel.
1439
- * let fragSrc = `
1440
- * precision highp float;
1441
- *
1442
- * void main() {
1443
- * // Set each pixel's RGBA value to yellow.
1444
- * gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
1445
- * }
1446
- * `;
1447
- *
1448
- * function setup() {
1449
- * createCanvas(100, 100, WEBGL);
1450
- *
1451
- * // Create a p5.Shader object.
1452
- * let myShader = createShader(vertSrc, fragSrc);
1453
- *
1454
- * // Apply the p5.Shader object.
1455
- * shader(myShader);
1456
- *
1457
- * // Style the drawing surface.
1458
- * noStroke();
1459
- *
1460
- * // Add a plane as a drawing surface.
1461
- * plane(100, 100);
1462
- *
1463
- * describe('A yellow square.');
1464
- * }
1465
- * </code>
1466
- * </div>
1467
- *
1468
- * <div>
1469
- * <code>
1470
- * // Note: A "uniform" is a global variable within a shader program.
1471
- *
1472
- * let mandelbrot;
1473
- *
1474
- * async function setup() {
1475
- * mandelbrot = await loadShader('assets/shader.vert', 'assets/shader.frag');
1476
- * createCanvas(100, 100, WEBGL);
1477
- *
1478
- * // Use the p5.Shader object.
1479
- * shader(mandelbrot);
1480
- *
1481
- * // Set the shader uniform p to an array.
1482
- * mandelbrot.setUniform('p', [-0.74364388703, 0.13182590421]);
1483
- *
1484
- * describe('A fractal image zooms in and out of focus.');
1485
- * }
1486
- *
1487
- * function draw() {
1488
- * // Set the shader uniform r to a value that oscillates between 0 and 2.
1489
- * mandelbrot.setUniform('r', sin(frameCount * 0.01) + 1);
1490
- *
1491
- * // Add a quad as a display surface for the shader.
1492
- * quad(-1, -1, 1, -1, 1, 1, -1, 1);
1493
- * }
1494
- * </code>
1495
- * </div>
1496
- */
1497
- p5.Shader = Shader;
1498
- }
1499
-
1500
- export default shader;
1501
- export { Shader };
1502
-
1503
- if(typeof p5 !== 'undefined'){
1504
- shader(p5, p5.prototype);
1505
- }