p5 2.3.0 → 2.3.1-rc.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.
- package/README.md +3 -11
- package/dist/accessibility/color_namer.js +7 -7
- package/dist/accessibility/index.js +7 -7
- package/dist/app.js +7 -7
- package/dist/app.node.js +7 -7
- package/dist/color/color_conversion.js +7 -7
- package/dist/color/creating_reading.js +1 -1
- package/dist/color/index.js +2 -2
- package/dist/color/p5.Color.js +1 -1
- package/dist/color/setting.js +2 -2
- package/dist/{constants-Dv6ZqA6s.js → constants-Bx3_xAam.js} +1 -1
- package/dist/core/constants.js +1 -1
- package/dist/core/environment.js +1 -1
- package/dist/core/filterShaders.js +1 -1
- package/dist/core/friendly_errors/fes_core.js +1 -1
- package/dist/core/friendly_errors/file_errors.js +1 -1
- package/dist/core/friendly_errors/index.js +1 -1
- package/dist/core/friendly_errors/param_validator.js +1 -1
- package/dist/core/friendly_errors/sketch_verifier.js +1 -1
- package/dist/core/helpers.js +1 -1
- package/dist/core/init.js +7 -7
- package/dist/core/internationalization.js +1 -1
- package/dist/core/legacy.js +7 -7
- package/dist/core/main.js +7 -7
- package/dist/core/p5.Graphics.js +4 -4
- package/dist/core/p5.Renderer.js +3 -3
- package/dist/core/p5.Renderer2D.js +7 -7
- package/dist/core/p5.Renderer3D.js +4 -4
- package/dist/core/rendering.js +4 -4
- package/dist/{creating_reading-DLkHH80h.js → creating_reading-YUSK33h8.js} +8 -0
- package/dist/dom/dom.js +2 -2
- package/dist/dom/index.js +2 -2
- package/dist/dom/p5.Element.js +2 -2
- package/dist/dom/p5.MediaElement.js +2 -2
- package/dist/events/pointer.js +15 -0
- package/dist/image/const.js +1 -1
- package/dist/image/filterRenderer2D.js +6 -6
- package/dist/image/image.js +4 -4
- package/dist/image/index.js +4 -4
- package/dist/image/loading_displaying.js +4 -4
- package/dist/image/p5.Image.js +3 -3
- package/dist/io/files.js +4 -4
- package/dist/io/index.js +4 -4
- package/dist/{ir_builders-C8mrXj5z.js → ir_builders-CMXkjMoV.js} +34 -24
- package/dist/{main-BR2ALC_6.js → main-BpW7VbDr.js} +39 -208
- package/dist/math/Matrices/Matrix.js +1 -1
- package/dist/math/Matrices/MatrixNumjs.js +1 -1
- package/dist/math/calculation.js +669 -84
- package/dist/math/index.js +1 -1
- package/dist/math/p5.Matrix.js +1 -1
- package/dist/math/p5.Vector.js +9 -1
- package/dist/math/patch-vector.js +3 -1
- package/dist/math/trigonometry.js +399 -48
- package/dist/{p5.Renderer-XOvhEbJn.js → p5.Renderer-op0Y1WO6.js} +2 -2
- package/dist/{rendering-C5lX6zKm.js → rendering-SZ71KIDM.js} +24 -9
- package/dist/shape/2d_primitives.js +1 -1
- package/dist/shape/attributes.js +4 -3
- package/dist/shape/custom_shapes.js +205 -3
- package/dist/shape/index.js +2 -2
- package/dist/strands/ir_builders.js +1 -1
- package/dist/strands/p5.strands.js +26 -9
- package/dist/strands/strands_FES.js +8 -1
- package/dist/strands/strands_api.js +316 -21
- package/dist/strands/strands_conditionals.js +1 -1
- package/dist/strands/strands_for.js +1 -1
- package/dist/strands/strands_node.js +1 -1
- package/dist/strands/strands_ternary.js +1 -1
- package/dist/{strands_glslBackend-D6G3UyCs.js → strands_glslBackend-DMhOnoGl.js} +2 -2
- package/dist/type/index.js +3 -3
- package/dist/type/p5.Font.js +13 -4
- package/dist/type/textCore.js +3 -3
- package/dist/webgl/3d_primitives.js +4 -4
- package/dist/webgl/GeometryBuilder.js +1 -1
- package/dist/webgl/ShapeBuilder.js +1 -1
- package/dist/webgl/enums.js +1 -1
- package/dist/webgl/index.js +6 -6
- package/dist/webgl/interaction.js +1 -1
- package/dist/webgl/light.js +4 -4
- package/dist/webgl/loading.js +4 -4
- package/dist/webgl/material.js +4 -4
- package/dist/webgl/p5.Camera.js +4 -4
- package/dist/webgl/p5.Framebuffer.js +4 -4
- package/dist/webgl/p5.Geometry.js +1 -1
- package/dist/webgl/p5.Quat.js +1 -1
- package/dist/webgl/p5.RendererGL.js +6 -6
- package/dist/webgl/p5.Shader.js +5 -1
- package/dist/webgl/p5.Texture.js +4 -4
- package/dist/webgl/strands_glslBackend.js +2 -2
- package/dist/webgl/text.js +4 -4
- package/dist/webgl/utils.js +4 -4
- package/dist/webgpu/index.js +2 -2
- package/dist/webgpu/p5.RendererWebGPU.js +2 -2
- package/dist/webgpu/strands_wgslBackend.js +2 -2
- package/lib/p5.esm.js +1765 -405
- package/lib/p5.esm.min.js +1 -1
- package/lib/p5.js +1765 -405
- package/lib/p5.min.js +1 -1
- package/lib/p5.webgpu.esm.js +34 -3
- package/lib/p5.webgpu.js +34 -3
- package/lib/p5.webgpu.min.js +1 -1
- package/package.json +1 -1
- package/types/global.d.ts +5539 -2604
- package/types/p5.d.ts +2917 -1432
package/lib/p5.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! p5.js v2.3.
|
|
1
|
+
/*! p5.js v2.3.1-rc.1 June 24, 2026 */
|
|
2
2
|
/**
|
|
3
3
|
* @module Constants
|
|
4
4
|
* @submodule Constants
|
|
@@ -12,7 +12,7 @@ const _PI = Math.PI;
|
|
|
12
12
|
* @property {String} VERSION
|
|
13
13
|
* @final
|
|
14
14
|
*/
|
|
15
|
-
const VERSION = '2.3.
|
|
15
|
+
const VERSION = '2.3.1-rc.1';
|
|
16
16
|
|
|
17
17
|
// GRAPHICS RENDERER
|
|
18
18
|
/**
|
|
@@ -11357,6 +11357,14 @@ function creatingReading(p5, fn){
|
|
|
11357
11357
|
* The version of `color()` with four parameters interprets them as RGBA, HSBA,
|
|
11358
11358
|
* or HSLA colors, depending on the current `colorMode()`. The last parameter
|
|
11359
11359
|
* sets the alpha (transparency) value.
|
|
11360
|
+
* In p5.strands shader callbacks, `color()` accepts the same input
|
|
11361
|
+
* formats but returns a `vec4` instead of a `p5.Color` object, with
|
|
11362
|
+
* RGBA components normalized to the 0–1 range. All colors in strands
|
|
11363
|
+
* are RGB-based; `colorMode()` has no effect inside shader callbacks.
|
|
11364
|
+
* Color utility functions such as `red()`, `green()`, `blue()`,
|
|
11365
|
+
* `alpha()`, `hue()`, `saturation()`, `brightness()`, and
|
|
11366
|
+
* `lightness()` also return values in the 0–1 range when used in
|
|
11367
|
+
* strands.
|
|
11360
11368
|
*
|
|
11361
11369
|
* @method color
|
|
11362
11370
|
* @param {Number} gray number specifying value between white and black.
|
|
@@ -17530,7 +17538,7 @@ function _checkFileExtension(filename, extension) {
|
|
|
17530
17538
|
*/
|
|
17531
17539
|
|
|
17532
17540
|
|
|
17533
|
-
class Image {
|
|
17541
|
+
let Image$1 = class Image {
|
|
17534
17542
|
constructor(width, height) {
|
|
17535
17543
|
this.width = width;
|
|
17536
17544
|
this.height = height;
|
|
@@ -19313,7 +19321,7 @@ class Image {
|
|
|
19313
19321
|
}
|
|
19314
19322
|
}
|
|
19315
19323
|
}
|
|
19316
|
-
}
|
|
19324
|
+
};
|
|
19317
19325
|
function encodeAndDownloadGif(pImg, filename) {
|
|
19318
19326
|
const props = pImg.gifProperties;
|
|
19319
19327
|
|
|
@@ -19615,9 +19623,9 @@ function image$2(p5, fn){
|
|
|
19615
19623
|
* @param {Number} width
|
|
19616
19624
|
* @param {Number} height
|
|
19617
19625
|
*/
|
|
19618
|
-
p5.Image = Image;
|
|
19626
|
+
p5.Image = Image$1;
|
|
19619
19627
|
|
|
19620
|
-
Image.prototype._friendlyError = p5._friendlyError;
|
|
19628
|
+
Image$1.prototype._friendlyError = p5._friendlyError;
|
|
19621
19629
|
|
|
19622
19630
|
/**
|
|
19623
19631
|
* The image's width in pixels.
|
|
@@ -23465,6 +23473,14 @@ function vector(p5, fn) {
|
|
|
23465
23473
|
* @property z
|
|
23466
23474
|
* @name z
|
|
23467
23475
|
*/
|
|
23476
|
+
|
|
23477
|
+
/**
|
|
23478
|
+
* The dimensions of the vector
|
|
23479
|
+
* @type {Number}
|
|
23480
|
+
* @for p5.Vector
|
|
23481
|
+
* @property dimensions
|
|
23482
|
+
* @name dimensions
|
|
23483
|
+
*/
|
|
23468
23484
|
}
|
|
23469
23485
|
|
|
23470
23486
|
if (typeof p5 !== 'undefined') {
|
|
@@ -24012,6 +24028,47 @@ class EllipsePrimitive extends ShapePrimitive {
|
|
|
24012
24028
|
}
|
|
24013
24029
|
}
|
|
24014
24030
|
|
|
24031
|
+
class RectPrimitive extends ShapePrimitive {
|
|
24032
|
+
#x;
|
|
24033
|
+
#y;
|
|
24034
|
+
#w;
|
|
24035
|
+
#h;
|
|
24036
|
+
#tl;
|
|
24037
|
+
#tr;
|
|
24038
|
+
#br;
|
|
24039
|
+
#bl;
|
|
24040
|
+
#vertexCapacity = 1;
|
|
24041
|
+
|
|
24042
|
+
constructor(startVertex, x, y, w, h, tl, tr, br, bl) {
|
|
24043
|
+
super(startVertex);
|
|
24044
|
+
this.#x = x;
|
|
24045
|
+
this.#y = y;
|
|
24046
|
+
this.#w = w;
|
|
24047
|
+
this.#h = h;
|
|
24048
|
+
this.#tl = tl;
|
|
24049
|
+
this.#tr = tr;
|
|
24050
|
+
this.#br = br;
|
|
24051
|
+
this.#bl = bl;
|
|
24052
|
+
}
|
|
24053
|
+
|
|
24054
|
+
get x() { return this.#x; }
|
|
24055
|
+
get y() { return this.#y; }
|
|
24056
|
+
get w() { return this.#w; }
|
|
24057
|
+
get h() { return this.#h; }
|
|
24058
|
+
get tl() { return this.#tl; }
|
|
24059
|
+
get tr() { return this.#tr; }
|
|
24060
|
+
get br() { return this.#br; }
|
|
24061
|
+
get bl() { return this.#bl; }
|
|
24062
|
+
|
|
24063
|
+
get vertexCapacity() {
|
|
24064
|
+
return this.#vertexCapacity;
|
|
24065
|
+
}
|
|
24066
|
+
|
|
24067
|
+
accept(visitor) {
|
|
24068
|
+
visitor.visitRectPrimitive(this);
|
|
24069
|
+
}
|
|
24070
|
+
}
|
|
24071
|
+
|
|
24015
24072
|
// ---- TESSELLATION PRIMITIVES ----
|
|
24016
24073
|
|
|
24017
24074
|
class TriangleFan extends ShapePrimitive {
|
|
@@ -24494,6 +24551,42 @@ class Shape {
|
|
|
24494
24551
|
return primitive.addToShape(this);
|
|
24495
24552
|
}
|
|
24496
24553
|
|
|
24554
|
+
rectPrimitive(x, y, w, h, tl, tr, br, bl) {
|
|
24555
|
+
const startVertex = this.#createVertex(new Vector(x, y));
|
|
24556
|
+
const primitive = new RectPrimitive(startVertex, x, y, w, h, tl, tr, br, bl);
|
|
24557
|
+
return primitive.addToShape(this);
|
|
24558
|
+
}
|
|
24559
|
+
|
|
24560
|
+
point(x, y) {
|
|
24561
|
+
const v0 = this.#createVertex(new Vector(x, y));
|
|
24562
|
+
const primitive = new Point(v0);
|
|
24563
|
+
return primitive.addToShape(this);
|
|
24564
|
+
}
|
|
24565
|
+
|
|
24566
|
+
line(x1, y1, x2, y2) {
|
|
24567
|
+
const v0 = this.#createVertex(new Vector(x1, y1));
|
|
24568
|
+
const v1 = this.#createVertex(new Vector(x2, y2));
|
|
24569
|
+
const primitive = new Line(v0, v1);
|
|
24570
|
+
return primitive.addToShape(this);
|
|
24571
|
+
}
|
|
24572
|
+
|
|
24573
|
+
triangle(x1, y1, x2, y2, x3, y3) {
|
|
24574
|
+
const v0 = this.#createVertex(new Vector(x1, y1));
|
|
24575
|
+
const v1 = this.#createVertex(new Vector(x2, y2));
|
|
24576
|
+
const v2 = this.#createVertex(new Vector(x3, y3));
|
|
24577
|
+
const primitive = new Triangle(v0, v1, v2);
|
|
24578
|
+
return primitive.addToShape(this);
|
|
24579
|
+
}
|
|
24580
|
+
|
|
24581
|
+
quad(x1, y1, x2, y2, x3, y3, x4, y4) {
|
|
24582
|
+
const v0 = this.#createVertex(new Vector(x1, y1));
|
|
24583
|
+
const v1 = this.#createVertex(new Vector(x2, y2));
|
|
24584
|
+
const v2 = this.#createVertex(new Vector(x3, y3));
|
|
24585
|
+
const v3 = this.#createVertex(new Vector(x4, y4));
|
|
24586
|
+
const primitive = new Quad(v0, v1, v2, v3);
|
|
24587
|
+
return primitive.addToShape(this);
|
|
24588
|
+
}
|
|
24589
|
+
|
|
24497
24590
|
beginContour(shapeKind = PATH) {
|
|
24498
24591
|
if (this.at(-1)?.kind === EMPTY_PATH) {
|
|
24499
24592
|
this.contours.pop();
|
|
@@ -24598,6 +24691,9 @@ class PrimitiveVisitor {
|
|
|
24598
24691
|
visitEllipsePrimitive(ellipse) {
|
|
24599
24692
|
throw new Error('Method visitEllipsePrimitive() has not been implemented.');
|
|
24600
24693
|
}
|
|
24694
|
+
visitRectPrimitive(rect) {
|
|
24695
|
+
throw new Error('Method visitRectPrimitive() has not been implemented.');
|
|
24696
|
+
}
|
|
24601
24697
|
|
|
24602
24698
|
// isolated primitives
|
|
24603
24699
|
visitPoint(point) {
|
|
@@ -24801,6 +24897,62 @@ class PrimitiveToPath2DConverter extends PrimitiveVisitor {
|
|
|
24801
24897
|
this.path.moveTo(centerX + radiusX, centerY);
|
|
24802
24898
|
this.path.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, 2 * Math.PI);
|
|
24803
24899
|
}
|
|
24900
|
+
visitRectPrimitive(rect) {
|
|
24901
|
+
const x = rect.x;
|
|
24902
|
+
const y = rect.y;
|
|
24903
|
+
const w = rect.w;
|
|
24904
|
+
const h = rect.h;
|
|
24905
|
+
let tl = rect.tl;
|
|
24906
|
+
let tr = rect.tr;
|
|
24907
|
+
let br = rect.br;
|
|
24908
|
+
let bl = rect.bl;
|
|
24909
|
+
|
|
24910
|
+
if (typeof tl === 'undefined') {
|
|
24911
|
+
this.path.rect(x, y, w, h);
|
|
24912
|
+
} else {
|
|
24913
|
+
if (typeof tr === 'undefined') {
|
|
24914
|
+
tr = tl;
|
|
24915
|
+
}
|
|
24916
|
+
if (typeof br === 'undefined') {
|
|
24917
|
+
br = tr;
|
|
24918
|
+
}
|
|
24919
|
+
if (typeof bl === 'undefined') {
|
|
24920
|
+
bl = br;
|
|
24921
|
+
}
|
|
24922
|
+
|
|
24923
|
+
const absW = Math.abs(w);
|
|
24924
|
+
const absH = Math.abs(h);
|
|
24925
|
+
const hw = absW / 2;
|
|
24926
|
+
const hh = absH / 2;
|
|
24927
|
+
|
|
24928
|
+
if (absW < 2 * tl) {
|
|
24929
|
+
tl = hw;
|
|
24930
|
+
}
|
|
24931
|
+
if (absH < 2 * tl) {
|
|
24932
|
+
tl = hh;
|
|
24933
|
+
}
|
|
24934
|
+
if (absW < 2 * tr) {
|
|
24935
|
+
tr = hw;
|
|
24936
|
+
}
|
|
24937
|
+
if (absH < 2 * tr) {
|
|
24938
|
+
tr = hh;
|
|
24939
|
+
}
|
|
24940
|
+
if (absW < 2 * br) {
|
|
24941
|
+
br = hw;
|
|
24942
|
+
}
|
|
24943
|
+
if (absH < 2 * br) {
|
|
24944
|
+
br = hh;
|
|
24945
|
+
}
|
|
24946
|
+
if (absW < 2 * bl) {
|
|
24947
|
+
bl = hw;
|
|
24948
|
+
}
|
|
24949
|
+
if (absH < 2 * bl) {
|
|
24950
|
+
bl = hh;
|
|
24951
|
+
}
|
|
24952
|
+
|
|
24953
|
+
this.path.roundRect(x, y, w, h, [tl, tr, br, bl]);
|
|
24954
|
+
}
|
|
24955
|
+
}
|
|
24804
24956
|
visitQuadStrip(quadStrip) {
|
|
24805
24957
|
for (let i = 0; i < quadStrip.vertices.length - 3; i += 2) {
|
|
24806
24958
|
const v0 = quadStrip.vertices[i];
|
|
@@ -24997,6 +25149,72 @@ class PrimitiveToVerticesConverter extends PrimitiveVisitor {
|
|
|
24997
25149
|
verts.push(new Vertex(vertexProps));
|
|
24998
25150
|
}
|
|
24999
25151
|
|
|
25152
|
+
this.contours.push(verts);
|
|
25153
|
+
}
|
|
25154
|
+
visitRectPrimitive(rect) {
|
|
25155
|
+
const x = rect.x;
|
|
25156
|
+
const y = rect.y;
|
|
25157
|
+
const w = rect.w;
|
|
25158
|
+
const h = rect.h;
|
|
25159
|
+
let tl = rect.tl;
|
|
25160
|
+
let tr = rect.tr;
|
|
25161
|
+
let br = rect.br;
|
|
25162
|
+
let bl = rect.bl;
|
|
25163
|
+
|
|
25164
|
+
const startVertex = rect.vertices[0];
|
|
25165
|
+
const getVertexProps = (px, py) => {
|
|
25166
|
+
const props = {};
|
|
25167
|
+
for (const [key, value] of Object.entries(startVertex)) {
|
|
25168
|
+
if (key === 'position') continue;
|
|
25169
|
+
props[key] = value;
|
|
25170
|
+
}
|
|
25171
|
+
props.position = new Vector(px, py);
|
|
25172
|
+
return new Vertex(props);
|
|
25173
|
+
};
|
|
25174
|
+
|
|
25175
|
+
const verts = [];
|
|
25176
|
+
if (typeof tl === 'undefined') {
|
|
25177
|
+
verts.push(getVertexProps(x, y));
|
|
25178
|
+
verts.push(getVertexProps(x + w, y));
|
|
25179
|
+
verts.push(getVertexProps(x + w, y + h));
|
|
25180
|
+
verts.push(getVertexProps(x, y + h));
|
|
25181
|
+
verts.push(getVertexProps(x, y));
|
|
25182
|
+
} else {
|
|
25183
|
+
if (typeof tr === 'undefined') tr = tl;
|
|
25184
|
+
if (typeof br === 'undefined') br = tr;
|
|
25185
|
+
if (typeof bl === 'undefined') bl = br;
|
|
25186
|
+
|
|
25187
|
+
const absW = Math.abs(w);
|
|
25188
|
+
const absH = Math.abs(h);
|
|
25189
|
+
const hw = absW / 2;
|
|
25190
|
+
const hh = absH / 2;
|
|
25191
|
+
|
|
25192
|
+
if (absW < 2 * tl) tl = hw;
|
|
25193
|
+
if (absH < 2 * tl) tl = hh;
|
|
25194
|
+
if (absW < 2 * tr) tr = hw;
|
|
25195
|
+
if (absH < 2 * tr) tr = hh;
|
|
25196
|
+
if (absW < 2 * br) br = hw;
|
|
25197
|
+
if (absH < 2 * br) br = hh;
|
|
25198
|
+
if (absW < 2 * bl) bl = hw;
|
|
25199
|
+
if (absH < 2 * bl) bl = hh;
|
|
25200
|
+
|
|
25201
|
+
const addCornerArc = (cx, cy, rx, ry, startAngle, endAngle) => {
|
|
25202
|
+
const perimeter = Math.PI / 2 * (rx + ry) / 2;
|
|
25203
|
+
const numPoints = Math.max(1, Math.ceil(this.curveDetail * perimeter));
|
|
25204
|
+
for (let i = 0; i <= numPoints; i++) {
|
|
25205
|
+
const angle = startAngle + (endAngle - startAngle) * (i / numPoints);
|
|
25206
|
+
verts.push(getVertexProps(cx + rx * Math.cos(angle), cy + ry * Math.sin(angle)));
|
|
25207
|
+
}
|
|
25208
|
+
};
|
|
25209
|
+
|
|
25210
|
+
addCornerArc(x + tl, y + tl, tl, tl, Math.PI, 1.5 * Math.PI);
|
|
25211
|
+
addCornerArc(x + w - tr, y + tr, tr, tr, 1.5 * Math.PI, 2 * Math.PI);
|
|
25212
|
+
addCornerArc(x + w - br, y + h - br, br, br, 0, 0.5 * Math.PI);
|
|
25213
|
+
addCornerArc(x + bl, y + h - bl, bl, bl, 0.5 * Math.PI, Math.PI);
|
|
25214
|
+
|
|
25215
|
+
verts.push(verts[0]);
|
|
25216
|
+
}
|
|
25217
|
+
|
|
25000
25218
|
this.contours.push(verts);
|
|
25001
25219
|
}
|
|
25002
25220
|
}
|
|
@@ -26841,7 +27059,7 @@ class Renderer {
|
|
|
26841
27059
|
// get(x,y,w,h)
|
|
26842
27060
|
}
|
|
26843
27061
|
|
|
26844
|
-
const region = new Image(w*pd, h*pd);
|
|
27062
|
+
const region = new Image$1(w*pd, h*pd);
|
|
26845
27063
|
region.pixelDensity(pd);
|
|
26846
27064
|
region.canvas
|
|
26847
27065
|
.getContext('2d')
|
|
@@ -30602,8 +30820,9 @@ function attributes(p5, fn){
|
|
|
30602
30820
|
* Sets the width of the stroke used for points, lines, and the outlines of
|
|
30603
30821
|
* shapes.
|
|
30604
30822
|
*
|
|
30605
|
-
* Note: `strokeWeight()` is affected by transformations,
|
|
30606
|
-
* <a href="#/p5/scale">scale()</a>.
|
|
30823
|
+
* Note: In 2D mode, `strokeWeight()` is affected by transformations,
|
|
30824
|
+
* especially calls to <a href="#/p5/scale">scale()</a>. It isn't affected by
|
|
30825
|
+
* transformations in WebGL and WebGPU modes.
|
|
30607
30826
|
*
|
|
30608
30827
|
* Calling `strokeWeight()` without an argument returns the current stroke weight as a number.
|
|
30609
30828
|
*
|
|
@@ -38983,8 +39202,19 @@ function loadingDisplaying(p5, fn){
|
|
|
38983
39202
|
|
|
38984
39203
|
} else {
|
|
38985
39204
|
// Non-GIF Section
|
|
38986
|
-
const
|
|
38987
|
-
|
|
39205
|
+
const img = await new Promise((resolve, reject) => {
|
|
39206
|
+
const img = new Image();
|
|
39207
|
+
const blob = new Blob([data], { type: contentType });
|
|
39208
|
+
const url = URL.createObjectURL(blob);
|
|
39209
|
+
|
|
39210
|
+
img.onerror = e => reject(e);
|
|
39211
|
+
img.onload = () => {
|
|
39212
|
+
URL.revokeObjectURL(url);
|
|
39213
|
+
resolve(img);
|
|
39214
|
+
};
|
|
39215
|
+
|
|
39216
|
+
img.src = url;
|
|
39217
|
+
});
|
|
38988
39218
|
|
|
38989
39219
|
pImg.width = pImg.canvas.width = img.width;
|
|
38990
39220
|
pImg.height = pImg.canvas.height = img.height;
|
|
@@ -55054,7 +55284,11 @@ class Renderer3D extends Renderer {
|
|
|
55054
55284
|
// the next time a shader is used. However, the texture() function
|
|
55055
55285
|
// works differently and is global p5 state. If the p5 state has
|
|
55056
55286
|
// been cleared, we also need to clear the value in uSampler to match.
|
|
55057
|
-
|
|
55287
|
+
this._settingFillUniforms = true;
|
|
55288
|
+
if (this.states._tex || !fillShader._userSetSampler) {
|
|
55289
|
+
fillShader.setUniform("uSampler", this.states._tex || empty);
|
|
55290
|
+
}
|
|
55291
|
+
this._settingFillUniforms = false;
|
|
55058
55292
|
fillShader.setUniform(
|
|
55059
55293
|
"uTint",
|
|
55060
55294
|
this.states.tint?._getRGBA([255, 255, 255, 255]) ?? [255, 255, 255, 255]
|
|
@@ -55177,7 +55411,7 @@ class Renderer3D extends Renderer {
|
|
|
55177
55411
|
_getEmptyTexture() {
|
|
55178
55412
|
if (!this._emptyTexture) {
|
|
55179
55413
|
// a plain white texture RGBA, full alpha, single pixel.
|
|
55180
|
-
const im = new Image(1, 1);
|
|
55414
|
+
const im = new Image$1(1, 1);
|
|
55181
55415
|
im.set(0, 0, 255);
|
|
55182
55416
|
this._emptyTexture = new Texture(this, im);
|
|
55183
55417
|
}
|
|
@@ -60621,7 +60855,7 @@ class Shader {
|
|
|
60621
60855
|
* @returns {String} The GLSL version used by the shader.
|
|
60622
60856
|
*/
|
|
60623
60857
|
version() {
|
|
60624
|
-
const match = /#version (.+)
|
|
60858
|
+
const match = /#version (.+)$/m.exec(this.vertSrc());
|
|
60625
60859
|
if (match) {
|
|
60626
60860
|
return match[1];
|
|
60627
60861
|
} else {
|
|
@@ -61625,6 +61859,10 @@ class Shader {
|
|
|
61625
61859
|
return;
|
|
61626
61860
|
}
|
|
61627
61861
|
|
|
61862
|
+
if (uniformName === 'uSampler' && !this._renderer._settingFillUniforms) {
|
|
61863
|
+
this._userSetSampler = true;
|
|
61864
|
+
}
|
|
61865
|
+
|
|
61628
61866
|
// In p5.strands-related code, where some of the code may be in
|
|
61629
61867
|
// p5.webgpu.js instead of the main p5.js build, we generally use
|
|
61630
61868
|
// duck typing instead of instanceof to avoid accidentally importing
|
|
@@ -63936,7 +64174,7 @@ function material(p5, fn) {
|
|
|
63936
64174
|
* // Replace alpha in the color with dithering by
|
|
63937
64175
|
* // randomly setting pixel colors to 0 based on opacity
|
|
63938
64176
|
* let a = 1;
|
|
63939
|
-
* if (
|
|
64177
|
+
* if (random() > pixelInputs.color.a) {
|
|
63940
64178
|
* a = 0;
|
|
63941
64179
|
* }
|
|
63942
64180
|
* pixelInputs.color.a = a;
|
|
@@ -65766,11 +66004,7 @@ function trigonometry(p5, fn){
|
|
|
65766
66004
|
* <a href="#/p5/angleMode">angleMode()</a> is `DEGREES`, then values are
|
|
65767
66005
|
* returned in the range 0 to 180.
|
|
65768
66006
|
*
|
|
65769
|
-
*
|
|
65770
|
-
* @param {Number} value value whose arc cosine is to be returned.
|
|
65771
|
-
* @return {Number} arc cosine of the given value.
|
|
65772
|
-
*
|
|
65773
|
-
* @example
|
|
66007
|
+
* ```js example
|
|
65774
66008
|
* function setup() {
|
|
65775
66009
|
* createCanvas(100, 100);
|
|
65776
66010
|
*
|
|
@@ -65788,8 +66022,9 @@ function trigonometry(p5, fn){
|
|
|
65788
66022
|
*
|
|
65789
66023
|
* describe('The numbers 3.142, -1, and 3.142 written on separate rows.');
|
|
65790
66024
|
* }
|
|
66025
|
+
* ```
|
|
65791
66026
|
*
|
|
65792
|
-
*
|
|
66027
|
+
* ```js example
|
|
65793
66028
|
* function setup() {
|
|
65794
66029
|
* createCanvas(100, 100);
|
|
65795
66030
|
*
|
|
@@ -65807,6 +66042,52 @@ function trigonometry(p5, fn){
|
|
|
65807
66042
|
*
|
|
65808
66043
|
* describe('The numbers 3.927, -0.707, and 2.356 written on separate rows.');
|
|
65809
66044
|
* }
|
|
66045
|
+
* ```
|
|
66046
|
+
*
|
|
66047
|
+
* `acos()` can also be used in shaders with p5.strands. The following example
|
|
66048
|
+
* uses `acos()` to create a pulsing color transition on a shape.
|
|
66049
|
+
*
|
|
66050
|
+
* ```js example
|
|
66051
|
+
* let myShader;
|
|
66052
|
+
*
|
|
66053
|
+
* function setup() {
|
|
66054
|
+
* createCanvas(100, 100, WEBGL);
|
|
66055
|
+
* myShader = buildColorShader(shaderCallback);
|
|
66056
|
+
* describe('A sphere that pulses between orange and teal.');
|
|
66057
|
+
* }
|
|
66058
|
+
*
|
|
66059
|
+
* function shaderCallback() {
|
|
66060
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
66061
|
+
* let t = millis() * 0.001;
|
|
66062
|
+
*
|
|
66063
|
+
* // acos(cos(t)) creates a triangle wave that goes from 0 to PI and back.
|
|
66064
|
+
* // Dividing by PI normalizes the result to the 0 to 1 range.
|
|
66065
|
+
* let value = acos(cos(t)) / PI;
|
|
66066
|
+
*
|
|
66067
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
66068
|
+
* let orange = [1, 0.5, 0, 1];
|
|
66069
|
+
* let teal = [0, 0.8, 0.8, 1];
|
|
66070
|
+
*
|
|
66071
|
+
* finalColor.begin();
|
|
66072
|
+
*
|
|
66073
|
+
* // mix() blends between orange (when value = 0) and teal (when value = 1).
|
|
66074
|
+
* // acos() creates a pulsing effect by turning smooth oscillation into a triangle wave.
|
|
66075
|
+
* finalColor.set(mix(orange, teal, value));
|
|
66076
|
+
*
|
|
66077
|
+
* finalColor.end();
|
|
66078
|
+
* }
|
|
66079
|
+
*
|
|
66080
|
+
* function draw() {
|
|
66081
|
+
* background(220);
|
|
66082
|
+
* shader(myShader);
|
|
66083
|
+
* noStroke();
|
|
66084
|
+
* sphere(30);
|
|
66085
|
+
* }
|
|
66086
|
+
* ```
|
|
66087
|
+
*
|
|
66088
|
+
* @method acos
|
|
66089
|
+
* @param {Number} value value whose arc cosine is to be returned.
|
|
66090
|
+
* @return {Number} arc cosine of the given value.
|
|
65810
66091
|
*/
|
|
65811
66092
|
fn.acos = function(ratio) {
|
|
65812
66093
|
return this._fromRadians(Math.acos(ratio));
|
|
@@ -65821,11 +66102,7 @@ function trigonometry(p5, fn){
|
|
|
65821
66102
|
* the <a href="#/p5/angleMode">angleMode()</a> is `DEGREES` then values are
|
|
65822
66103
|
* returned in the range -90 to 90.
|
|
65823
66104
|
*
|
|
65824
|
-
*
|
|
65825
|
-
* @param {Number} value value whose arc sine is to be returned.
|
|
65826
|
-
* @return {Number} arc sine of the given value.
|
|
65827
|
-
*
|
|
65828
|
-
* @example
|
|
66105
|
+
* ```js example
|
|
65829
66106
|
* function setup() {
|
|
65830
66107
|
* createCanvas(100, 100);
|
|
65831
66108
|
*
|
|
@@ -65843,8 +66120,9 @@ function trigonometry(p5, fn){
|
|
|
65843
66120
|
*
|
|
65844
66121
|
* describe('The numbers 1.047, 0.866, and 1.047 written on separate rows.');
|
|
65845
66122
|
* }
|
|
66123
|
+
* ```
|
|
65846
66124
|
*
|
|
65847
|
-
*
|
|
66125
|
+
* ```js example
|
|
65848
66126
|
* function setup() {
|
|
65849
66127
|
* createCanvas(100, 100);
|
|
65850
66128
|
*
|
|
@@ -65862,6 +66140,52 @@ function trigonometry(p5, fn){
|
|
|
65862
66140
|
*
|
|
65863
66141
|
* describe('The numbers 4.189, -0.866, and -1.047 written on separate rows.');
|
|
65864
66142
|
* }
|
|
66143
|
+
* ```
|
|
66144
|
+
*
|
|
66145
|
+
* `asin()` can also be used in shaders with p5.strands. The following example
|
|
66146
|
+
* uses `asin()` to create a smooth color transition on a shape.
|
|
66147
|
+
*
|
|
66148
|
+
* ```js example
|
|
66149
|
+
* let myShader;
|
|
66150
|
+
*
|
|
66151
|
+
* function setup() {
|
|
66152
|
+
* createCanvas(100, 100, WEBGL);
|
|
66153
|
+
* myShader = buildColorShader(shaderCallback);
|
|
66154
|
+
* describe('A sphere that smoothly shifts between green and purple.');
|
|
66155
|
+
* }
|
|
66156
|
+
*
|
|
66157
|
+
* function shaderCallback() {
|
|
66158
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
66159
|
+
* let t = millis() * 0.001;
|
|
66160
|
+
*
|
|
66161
|
+
* // asin(sin(t)) returns a value between -PI/2 and PI/2.
|
|
66162
|
+
* // Dividing by PI/2 normalizes to -1 to 1, then adding 1 and multiplying by 0.5
|
|
66163
|
+
* // remaps to the 0 to 1 range.
|
|
66164
|
+
* let value = (asin(sin(t)) / (PI / 2) + 1) * 0.5;
|
|
66165
|
+
*
|
|
66166
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
66167
|
+
* let green = [0, 1, 0.5, 1];
|
|
66168
|
+
* let purple = [0.5, 0, 1, 1];
|
|
66169
|
+
*
|
|
66170
|
+
* finalColor.begin();
|
|
66171
|
+
*
|
|
66172
|
+
* // mix() blends between green (when value = 0) and purple (when value = 1).
|
|
66173
|
+
* finalColor.set(mix(green, purple, value));
|
|
66174
|
+
*
|
|
66175
|
+
* finalColor.end();
|
|
66176
|
+
* }
|
|
66177
|
+
*
|
|
66178
|
+
* function draw() {
|
|
66179
|
+
* background(220);
|
|
66180
|
+
* shader(myShader);
|
|
66181
|
+
* noStroke();
|
|
66182
|
+
* sphere(30);
|
|
66183
|
+
* }
|
|
66184
|
+
* ```
|
|
66185
|
+
*
|
|
66186
|
+
* @method asin
|
|
66187
|
+
* @param {Number} value value whose arc sine is to be returned.
|
|
66188
|
+
* @return {Number} arc sine of the given value.
|
|
65865
66189
|
*/
|
|
65866
66190
|
fn.asin = function(ratio) {
|
|
65867
66191
|
return this._fromRadians(Math.asin(ratio));
|
|
@@ -65876,11 +66200,7 @@ function trigonometry(p5, fn){
|
|
|
65876
66200
|
* (about 1.57). If the <a href="#/p5/angleMode">angleMode()</a> is `DEGREES`
|
|
65877
66201
|
* then values are returned in the range -90 to 90.
|
|
65878
66202
|
*
|
|
65879
|
-
*
|
|
65880
|
-
* @param {Number} value value whose arc tangent is to be returned.
|
|
65881
|
-
* @return {Number} arc tangent of the given value.
|
|
65882
|
-
*
|
|
65883
|
-
* @example
|
|
66203
|
+
* ```js example
|
|
65884
66204
|
* function setup() {
|
|
65885
66205
|
* createCanvas(100, 100);
|
|
65886
66206
|
*
|
|
@@ -65898,8 +66218,9 @@ function trigonometry(p5, fn){
|
|
|
65898
66218
|
*
|
|
65899
66219
|
* describe('The numbers 1.047, 1.732, and 1.047 written on separate rows.');
|
|
65900
66220
|
* }
|
|
66221
|
+
* ```
|
|
65901
66222
|
*
|
|
65902
|
-
*
|
|
66223
|
+
* ```js example
|
|
65903
66224
|
* function setup() {
|
|
65904
66225
|
* createCanvas(100, 100);
|
|
65905
66226
|
*
|
|
@@ -65917,6 +66238,55 @@ function trigonometry(p5, fn){
|
|
|
65917
66238
|
*
|
|
65918
66239
|
* describe('The numbers 4.189, 1.732, and 1.047 written on separate rows.');
|
|
65919
66240
|
* }
|
|
66241
|
+
* ```
|
|
66242
|
+
*
|
|
66243
|
+
* `atan()` can also be used in shaders with p5.strands. The following example
|
|
66244
|
+
* uses `atan()` to create a soft color transition on a shape.
|
|
66245
|
+
*
|
|
66246
|
+
* ```js example
|
|
66247
|
+
* let myShader;
|
|
66248
|
+
*
|
|
66249
|
+
* function setup() {
|
|
66250
|
+
* createCanvas(100, 100, WEBGL);
|
|
66251
|
+
* myShader = buildColorShader(shaderCallback);
|
|
66252
|
+
* describe('A sphere that softly shifts between pink and lime.');
|
|
66253
|
+
* }
|
|
66254
|
+
*
|
|
66255
|
+
* function shaderCallback() {
|
|
66256
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
66257
|
+
* // sin() oscillates the input between -5 and 5, so atan() gets both positive and negative values.
|
|
66258
|
+
* let t = sin(millis() * 0.001) * 5;
|
|
66259
|
+
*
|
|
66260
|
+
* // atan(t) returns values between -PI/2 and PI/2.
|
|
66261
|
+
* // Dividing by PI/2 normalizes to -1 to 1, then adding 1 and multiplying by 0.5
|
|
66262
|
+
* // remaps to the 0 to 1 range.
|
|
66263
|
+
* // atan() compresses the wide range of t into a smooth S-curve (soft clipping).
|
|
66264
|
+
* let value = (atan(t) / (PI / 2) + 1) * 0.5;
|
|
66265
|
+
*
|
|
66266
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
66267
|
+
* let pink = [1, 0, 0.5, 1];
|
|
66268
|
+
* let lime = [0.5, 1, 0, 1];
|
|
66269
|
+
*
|
|
66270
|
+
* finalColor.begin();
|
|
66271
|
+
*
|
|
66272
|
+
* // mix() blends between pink (when value = 0) and lime (when value = 1).
|
|
66273
|
+
* // atan() creates a soft, eased transition instead of a linear blend.
|
|
66274
|
+
* finalColor.set(mix(pink, lime, value));
|
|
66275
|
+
*
|
|
66276
|
+
* finalColor.end();
|
|
66277
|
+
* }
|
|
66278
|
+
*
|
|
66279
|
+
* function draw() {
|
|
66280
|
+
* background(220);
|
|
66281
|
+
* shader(myShader);
|
|
66282
|
+
* noStroke();
|
|
66283
|
+
* sphere(30);
|
|
66284
|
+
* }
|
|
66285
|
+
* ```
|
|
66286
|
+
*
|
|
66287
|
+
* @method atan
|
|
66288
|
+
* @param {Number} value value whose arc tangent is to be returned.
|
|
66289
|
+
* @return {Number} arc tangent of the given value.
|
|
65920
66290
|
*/
|
|
65921
66291
|
fn.atan = function(ratio) {
|
|
65922
66292
|
return this._fromRadians(Math.atan(ratio));
|
|
@@ -66000,11 +66370,7 @@ function trigonometry(p5, fn){
|
|
|
66000
66370
|
* calculates the cosine of an angle, using radians by default, or according
|
|
66001
66371
|
* to if <a href="#/p5/angleMode">angleMode()</a> setting (RADIANS or DEGREES).
|
|
66002
66372
|
*
|
|
66003
|
-
*
|
|
66004
|
-
* @param {Number} angle the angle, in radians by default, or according to if <a href="/reference/p5/angleMode/">angleMode()</a> setting (RADIANS or DEGREES).
|
|
66005
|
-
* @return {Number} cosine of the angle.
|
|
66006
|
-
*
|
|
66007
|
-
* @example
|
|
66373
|
+
* ```js example
|
|
66008
66374
|
* function setup() {
|
|
66009
66375
|
* createCanvas(100, 100);
|
|
66010
66376
|
*
|
|
@@ -66022,8 +66388,9 @@ function trigonometry(p5, fn){
|
|
|
66022
66388
|
* line(50, y, x, y);
|
|
66023
66389
|
* circle(x, y, 20);
|
|
66024
66390
|
* }
|
|
66391
|
+
* ```
|
|
66025
66392
|
*
|
|
66026
|
-
*
|
|
66393
|
+
* ```js example
|
|
66027
66394
|
* function setup() {
|
|
66028
66395
|
* createCanvas(100, 100);
|
|
66029
66396
|
*
|
|
@@ -66040,8 +66407,9 @@ function trigonometry(p5, fn){
|
|
|
66040
66407
|
* // Draw the point.
|
|
66041
66408
|
* point(x, y);
|
|
66042
66409
|
* }
|
|
66410
|
+
* ```
|
|
66043
66411
|
*
|
|
66044
|
-
*
|
|
66412
|
+
* ```js example
|
|
66045
66413
|
* function setup() {
|
|
66046
66414
|
* createCanvas(100, 100);
|
|
66047
66415
|
*
|
|
@@ -66058,6 +66426,51 @@ function trigonometry(p5, fn){
|
|
|
66058
66426
|
* // Draw the point.
|
|
66059
66427
|
* point(x, y);
|
|
66060
66428
|
* }
|
|
66429
|
+
* ```
|
|
66430
|
+
*
|
|
66431
|
+
* `cos()` can also be used in shaders with p5.strands. The following example
|
|
66432
|
+
* uses `cos()` to smoothly oscillate the color of a shape over time.
|
|
66433
|
+
*
|
|
66434
|
+
* ```js example
|
|
66435
|
+
* let myShader;
|
|
66436
|
+
*
|
|
66437
|
+
* function setup() {
|
|
66438
|
+
* createCanvas(100, 100, WEBGL);
|
|
66439
|
+
* myShader = buildColorShader(shaderCallback);
|
|
66440
|
+
* describe('A sphere that fades between yellow and blue.');
|
|
66441
|
+
* }
|
|
66442
|
+
*
|
|
66443
|
+
* function shaderCallback() {
|
|
66444
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
66445
|
+
* let t = millis() * 0.001;
|
|
66446
|
+
*
|
|
66447
|
+
* // cos(t) oscillates between -1 and 1.
|
|
66448
|
+
* // 0.5 + 0.5 * cos(t) remaps this to the 0 to 1 range.
|
|
66449
|
+
* let value = 0.5 + 0.5 * cos(t);
|
|
66450
|
+
*
|
|
66451
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
66452
|
+
* let yellow = [1, 1, 0, 1];
|
|
66453
|
+
* let blue = [0, 0, 1, 1];
|
|
66454
|
+
*
|
|
66455
|
+
* finalColor.begin();
|
|
66456
|
+
*
|
|
66457
|
+
* // mix() blends between yellow (when value = 0) and blue (when value = 1).
|
|
66458
|
+
* finalColor.set(mix(yellow, blue, value));
|
|
66459
|
+
*
|
|
66460
|
+
* finalColor.end();
|
|
66461
|
+
* }
|
|
66462
|
+
*
|
|
66463
|
+
* function draw() {
|
|
66464
|
+
* background(220);
|
|
66465
|
+
* shader(myShader);
|
|
66466
|
+
* noStroke();
|
|
66467
|
+
* sphere(30);
|
|
66468
|
+
* }
|
|
66469
|
+
* ```
|
|
66470
|
+
*
|
|
66471
|
+
* @method cos
|
|
66472
|
+
* @param {Number} angle the angle, in radians by default, or according to if <a href="/reference/p5/angleMode/">angleMode()</a> setting (RADIANS or DEGREES).
|
|
66473
|
+
* @return {Number} cosine of the angle.
|
|
66061
66474
|
*/
|
|
66062
66475
|
fn.cos = function(angle) {
|
|
66063
66476
|
return Math.cos(this._toRadians(angle));
|
|
@@ -66071,11 +66484,7 @@ function trigonometry(p5, fn){
|
|
|
66071
66484
|
* calculates the sine of an angle, using radians by default, or according to
|
|
66072
66485
|
* if <a href="#/p5/angleMode">angleMode()</a> setting (RADIANS or DEGREES).
|
|
66073
66486
|
*
|
|
66074
|
-
*
|
|
66075
|
-
* @param {Number} angle the angle, in radians by default, or according to if <a href="/reference/p5/angleMode/">angleMode()</a> setting (RADIANS or DEGREES).
|
|
66076
|
-
* @return {Number} sine of the angle.
|
|
66077
|
-
*
|
|
66078
|
-
* @example
|
|
66487
|
+
* ```js example
|
|
66079
66488
|
* function setup() {
|
|
66080
66489
|
* createCanvas(100, 100);
|
|
66081
66490
|
*
|
|
@@ -66093,8 +66502,9 @@ function trigonometry(p5, fn){
|
|
|
66093
66502
|
* line(50, y, x, y);
|
|
66094
66503
|
* circle(x, y, 20);
|
|
66095
66504
|
* }
|
|
66505
|
+
* ```
|
|
66096
66506
|
*
|
|
66097
|
-
*
|
|
66507
|
+
* ```js example
|
|
66098
66508
|
* function setup() {
|
|
66099
66509
|
* createCanvas(100, 100);
|
|
66100
66510
|
*
|
|
@@ -66111,8 +66521,9 @@ function trigonometry(p5, fn){
|
|
|
66111
66521
|
* // Draw the point.
|
|
66112
66522
|
* point(x, y);
|
|
66113
66523
|
* }
|
|
66524
|
+
* ```
|
|
66114
66525
|
*
|
|
66115
|
-
*
|
|
66526
|
+
* ```js example
|
|
66116
66527
|
* function setup() {
|
|
66117
66528
|
* createCanvas(100, 100);
|
|
66118
66529
|
*
|
|
@@ -66129,6 +66540,51 @@ function trigonometry(p5, fn){
|
|
|
66129
66540
|
* // Draw the point.
|
|
66130
66541
|
* point(x, y);
|
|
66131
66542
|
* }
|
|
66543
|
+
* ```
|
|
66544
|
+
*
|
|
66545
|
+
* `sin()` can also be used in shaders with p5.strands. The following example
|
|
66546
|
+
* uses `sin()` to oscillate the color of a shape over time.
|
|
66547
|
+
*
|
|
66548
|
+
* ```js example
|
|
66549
|
+
* let myShader;
|
|
66550
|
+
*
|
|
66551
|
+
* function setup() {
|
|
66552
|
+
* createCanvas(100, 100, WEBGL);
|
|
66553
|
+
* myShader = buildColorShader(shaderCallback);
|
|
66554
|
+
* describe('A sphere that pulses between cyan and magenta.');
|
|
66555
|
+
* }
|
|
66556
|
+
*
|
|
66557
|
+
* function shaderCallback() {
|
|
66558
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
66559
|
+
* let t = millis() * 0.001;
|
|
66560
|
+
*
|
|
66561
|
+
* // sin(t) oscillates between -1 and 1.
|
|
66562
|
+
* // 0.5 + 0.5 * sin(t) remaps this to the 0 to 1 range.
|
|
66563
|
+
* let value = 0.5 + 0.5 * sin(t);
|
|
66564
|
+
*
|
|
66565
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
66566
|
+
* let cyan = [0, 1, 1, 1];
|
|
66567
|
+
* let magenta = [1, 0, 1, 1];
|
|
66568
|
+
*
|
|
66569
|
+
* finalColor.begin();
|
|
66570
|
+
*
|
|
66571
|
+
* // mix() blends between cyan (when value = 0) and magenta (when value = 1).
|
|
66572
|
+
* finalColor.set(mix(cyan, magenta, value));
|
|
66573
|
+
*
|
|
66574
|
+
* finalColor.end();
|
|
66575
|
+
* }
|
|
66576
|
+
*
|
|
66577
|
+
* function draw() {
|
|
66578
|
+
* background(220);
|
|
66579
|
+
* shader(myShader);
|
|
66580
|
+
* noStroke();
|
|
66581
|
+
* sphere(30);
|
|
66582
|
+
* }
|
|
66583
|
+
* ```
|
|
66584
|
+
*
|
|
66585
|
+
* @method sin
|
|
66586
|
+
* @param {Number} angle the angle, in radians by default, or according to if <a href="/reference/p5/angleMode/">angleMode()</a> setting (RADIANS or DEGREES).
|
|
66587
|
+
* @return {Number} sine of the angle.
|
|
66132
66588
|
*/
|
|
66133
66589
|
fn.sin = function(angle) {
|
|
66134
66590
|
return Math.sin(this._toRadians(angle));
|
|
@@ -66143,11 +66599,7 @@ function trigonometry(p5, fn){
|
|
|
66143
66599
|
* by default, or according to
|
|
66144
66600
|
* if <a href="#/p5/angleMode">angleMode()</a> setting (RADIANS or DEGREES).
|
|
66145
66601
|
*
|
|
66146
|
-
*
|
|
66147
|
-
* @param {Number} angle the angle, in radians by default, or according to if <a href="/reference/p5/angleMode/">angleMode()</a> setting (RADIANS or DEGREES).
|
|
66148
|
-
* @return {Number} tangent of the angle.
|
|
66149
|
-
*
|
|
66150
|
-
* @example
|
|
66602
|
+
* ```js example
|
|
66151
66603
|
* function setup() {
|
|
66152
66604
|
* createCanvas(100, 100);
|
|
66153
66605
|
*
|
|
@@ -66164,6 +66616,53 @@ function trigonometry(p5, fn){
|
|
|
66164
66616
|
* // Draw the point.
|
|
66165
66617
|
* point(x, y);
|
|
66166
66618
|
* }
|
|
66619
|
+
* ```
|
|
66620
|
+
*
|
|
66621
|
+
* `tan()` can also be used in shaders with p5.strands. The following example
|
|
66622
|
+
* uses `tan()` to create rapid color transitions on a shape.
|
|
66623
|
+
*
|
|
66624
|
+
* ```js example
|
|
66625
|
+
* let myShader;
|
|
66626
|
+
*
|
|
66627
|
+
* function setup() {
|
|
66628
|
+
* createCanvas(100, 100, WEBGL);
|
|
66629
|
+
* myShader = buildColorShader(shaderCallback);
|
|
66630
|
+
* describe('A sphere with rapidly shifting colors.');
|
|
66631
|
+
* }
|
|
66632
|
+
*
|
|
66633
|
+
* function shaderCallback() {
|
|
66634
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.0005 to slow it down.
|
|
66635
|
+
* let t = millis() * 0.0005;
|
|
66636
|
+
*
|
|
66637
|
+
* // tan(t) can grow to very large values (even infinity) at certain angles.
|
|
66638
|
+
* // 0.5 + 0.5 * tan(t) shifts the range but can still go way past 0 or 1.
|
|
66639
|
+
* // min(max(..., 0), 1) clamps the result to the 0 to 1 range.
|
|
66640
|
+
* let value = min(max(0.5 + 0.5 * tan(t), 0), 1);
|
|
66641
|
+
*
|
|
66642
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
66643
|
+
* let orange = [1, 0.5, 0, 1];
|
|
66644
|
+
* let blue = [0, 0.5, 1, 1];
|
|
66645
|
+
*
|
|
66646
|
+
* finalColor.begin();
|
|
66647
|
+
*
|
|
66648
|
+
* // mix() blends between orange (when value = 0) and blue (when value = 1).
|
|
66649
|
+
* // tan() creates rapid, dramatic color shifts as it spikes and resets.
|
|
66650
|
+
* finalColor.set(mix(orange, blue, value));
|
|
66651
|
+
*
|
|
66652
|
+
* finalColor.end();
|
|
66653
|
+
* }
|
|
66654
|
+
*
|
|
66655
|
+
* function draw() {
|
|
66656
|
+
* background(220);
|
|
66657
|
+
* shader(myShader);
|
|
66658
|
+
* noStroke();
|
|
66659
|
+
* sphere(30);
|
|
66660
|
+
* }
|
|
66661
|
+
* ```
|
|
66662
|
+
*
|
|
66663
|
+
* @method tan
|
|
66664
|
+
* @param {Number} angle the angle, in radians by default, or according to if <a href="/reference/p5/angleMode/">angleMode()</a> setting (RADIANS or DEGREES).
|
|
66665
|
+
* @return {Number} tangent of the angle.
|
|
66167
66666
|
*/
|
|
66168
66667
|
fn.tan = function(angle) {
|
|
66169
66668
|
return Math.tan(this._toRadians(angle));
|
|
@@ -66179,11 +66678,7 @@ function trigonometry(p5, fn){
|
|
|
66179
66678
|
* quarter of a full rotation. The same angle is 2 × π ÷ 4
|
|
66180
66679
|
* (about 1.57) radians.
|
|
66181
66680
|
*
|
|
66182
|
-
*
|
|
66183
|
-
* @param {Number} radians radians value to convert to degrees.
|
|
66184
|
-
* @return {Number} converted angle.
|
|
66185
|
-
*
|
|
66186
|
-
* @example
|
|
66681
|
+
* ```js example
|
|
66187
66682
|
* function setup() {
|
|
66188
66683
|
* createCanvas(100, 100);
|
|
66189
66684
|
*
|
|
@@ -66198,6 +66693,54 @@ function trigonometry(p5, fn){
|
|
|
66198
66693
|
*
|
|
66199
66694
|
* describe('The text "0.79 rad = 45˚".');
|
|
66200
66695
|
* }
|
|
66696
|
+
* ```
|
|
66697
|
+
*
|
|
66698
|
+
* `degrees()` can also be used in shaders with p5.strands. The following example
|
|
66699
|
+
* uses `degrees()` to convert a radian value to degrees inside a shader.
|
|
66700
|
+
*
|
|
66701
|
+
* ```js example
|
|
66702
|
+
* let myShader;
|
|
66703
|
+
*
|
|
66704
|
+
* function setup() {
|
|
66705
|
+
* createCanvas(100, 100, WEBGL);
|
|
66706
|
+
* myShader = buildColorShader(shaderCallback);
|
|
66707
|
+
* describe('A sphere that cycles through warm colors.');
|
|
66708
|
+
* }
|
|
66709
|
+
*
|
|
66710
|
+
* function shaderCallback() {
|
|
66711
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
66712
|
+
* let t = millis() * 0.001;
|
|
66713
|
+
*
|
|
66714
|
+
* // degrees() converts the radian value t to degrees.
|
|
66715
|
+
* // (deg % 360) wraps the degrees into a 0-360 range.
|
|
66716
|
+
* // Dividing by 360 normalizes to the 0 to 1 range.
|
|
66717
|
+
* let deg = degrees(t);
|
|
66718
|
+
* let value = (deg % 360) / 360;
|
|
66719
|
+
*
|
|
66720
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
66721
|
+
* let red = [1, 0, 0, 1];
|
|
66722
|
+
* let yellow = [1, 1, 0, 1];
|
|
66723
|
+
*
|
|
66724
|
+
* finalColor.begin();
|
|
66725
|
+
*
|
|
66726
|
+
* // mix() blends between red (when value = 0) and yellow (when value = 1).
|
|
66727
|
+
* // degrees() creates a cycling sawtooth pattern as time increases.
|
|
66728
|
+
* finalColor.set(mix(red, yellow, value));
|
|
66729
|
+
*
|
|
66730
|
+
* finalColor.end();
|
|
66731
|
+
* }
|
|
66732
|
+
*
|
|
66733
|
+
* function draw() {
|
|
66734
|
+
* background(220);
|
|
66735
|
+
* shader(myShader);
|
|
66736
|
+
* noStroke();
|
|
66737
|
+
* sphere(30);
|
|
66738
|
+
* }
|
|
66739
|
+
* ```
|
|
66740
|
+
*
|
|
66741
|
+
* @method degrees
|
|
66742
|
+
* @param {Number} radians radians value to convert to degrees.
|
|
66743
|
+
* @return {Number} converted angle.
|
|
66201
66744
|
*/
|
|
66202
66745
|
fn.degrees = angle => angle * RAD_TO_DEG;
|
|
66203
66746
|
|
|
@@ -66211,11 +66754,7 @@ function trigonometry(p5, fn){
|
|
|
66211
66754
|
* quarter of a full rotation. The same angle is 2 × π ÷ 4
|
|
66212
66755
|
* (about 1.57) radians.
|
|
66213
66756
|
*
|
|
66214
|
-
*
|
|
66215
|
-
* @param {Number} degrees degree value to convert to radians.
|
|
66216
|
-
* @return {Number} converted angle.
|
|
66217
|
-
*
|
|
66218
|
-
* @example
|
|
66757
|
+
* ```js example
|
|
66219
66758
|
* function setup() {
|
|
66220
66759
|
* createCanvas(100, 100);
|
|
66221
66760
|
*
|
|
@@ -66230,6 +66769,56 @@ function trigonometry(p5, fn){
|
|
|
66230
66769
|
*
|
|
66231
66770
|
* describe('The text "45˚ = 0.785 rad".');
|
|
66232
66771
|
* }
|
|
66772
|
+
* ```
|
|
66773
|
+
*
|
|
66774
|
+
* `radians()` can also be used in shaders with p5.strands. The following example
|
|
66775
|
+
* uses `radians()` to convert degrees to radians inside a shader.
|
|
66776
|
+
*
|
|
66777
|
+
* ```js example
|
|
66778
|
+
* let myShader;
|
|
66779
|
+
*
|
|
66780
|
+
* function setup() {
|
|
66781
|
+
* createCanvas(100, 100, WEBGL);
|
|
66782
|
+
* myShader = buildColorShader(shaderCallback);
|
|
66783
|
+
* describe('A sphere that fades between red and white.');
|
|
66784
|
+
* }
|
|
66785
|
+
*
|
|
66786
|
+
* function shaderCallback() {
|
|
66787
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start.
|
|
66788
|
+
* // Multiply by 0.05 and mod 360 to cycle through 0-360 degrees over time.
|
|
66789
|
+
* let deg = (millis() * 0.05) % 360;
|
|
66790
|
+
*
|
|
66791
|
+
* // radians() converts degrees to radians so sin() can use them.
|
|
66792
|
+
* let rad = radians(deg);
|
|
66793
|
+
*
|
|
66794
|
+
* // sin(rad) oscillates between -1 and 1.
|
|
66795
|
+
* // 0.5 + 0.5 * sin(rad) remaps this to the 0 to 1 range.
|
|
66796
|
+
* let value = 0.5 + 0.5 * sin(rad);
|
|
66797
|
+
*
|
|
66798
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
66799
|
+
* let red = [1, 0, 0, 1];
|
|
66800
|
+
* let white = [1, 1, 1, 1];
|
|
66801
|
+
*
|
|
66802
|
+
* finalColor.begin();
|
|
66803
|
+
*
|
|
66804
|
+
* // mix() blends between red (when value = 0) and white (when value = 1).
|
|
66805
|
+
* // radians() converts the degree input so sin() can produce smooth oscillation.
|
|
66806
|
+
* finalColor.set(mix(red, white, value));
|
|
66807
|
+
*
|
|
66808
|
+
* finalColor.end();
|
|
66809
|
+
* }
|
|
66810
|
+
*
|
|
66811
|
+
* function draw() {
|
|
66812
|
+
* background(220);
|
|
66813
|
+
* shader(myShader);
|
|
66814
|
+
* noStroke();
|
|
66815
|
+
* sphere(30);
|
|
66816
|
+
* }
|
|
66817
|
+
* ```
|
|
66818
|
+
*
|
|
66819
|
+
* @method radians
|
|
66820
|
+
* @param {Number} degrees degree value to convert to radians.
|
|
66821
|
+
* @return {Number} converted angle.
|
|
66233
66822
|
*/
|
|
66234
66823
|
fn.radians = angle => angle * DEG_TO_RAD;
|
|
66235
66824
|
|
|
@@ -67215,7 +67804,7 @@ class Texture {
|
|
|
67215
67804
|
_detectSourceType() {
|
|
67216
67805
|
const obj = this.src;
|
|
67217
67806
|
this.isFramebufferTexture = obj instanceof FramebufferTexture;
|
|
67218
|
-
this.isSrcP5Image = obj instanceof Image;
|
|
67807
|
+
this.isSrcP5Image = obj instanceof Image$1;
|
|
67219
67808
|
this.isSrcP5Graphics = obj instanceof Graphics;
|
|
67220
67809
|
this.isSrcP5Renderer = obj instanceof Renderer;
|
|
67221
67810
|
this.isImageData = typeof ImageData !== 'undefined' && obj instanceof ImageData;
|
|
@@ -70158,6 +70747,13 @@ function userError(errorType, errorMessage) {
|
|
|
70158
70747
|
throw new Error(prefixedMessage);
|
|
70159
70748
|
}
|
|
70160
70749
|
|
|
70750
|
+
function dimensionMismatchError(declaredDim,actualDim,varName){
|
|
70751
|
+
userError(
|
|
70752
|
+
'dimension mismatch',
|
|
70753
|
+
`Cannot assign a value of dimension ${actualDim} to \`${varName}\`, which expects dimension ${declaredDim}.`
|
|
70754
|
+
);
|
|
70755
|
+
}
|
|
70756
|
+
|
|
70161
70757
|
/////////////////////////////////
|
|
70162
70758
|
// Public functions for strands runtime
|
|
70163
70759
|
/////////////////////////////////
|
|
@@ -70446,6 +71042,16 @@ class StrandsNode {
|
|
|
70446
71042
|
|
|
70447
71043
|
// For varying variables, we need both assignment generation AND a way to reference by identifier
|
|
70448
71044
|
if (this._originalIdentifier) {
|
|
71045
|
+
const valueDim = value?.isStrandsNode
|
|
71046
|
+
? value.dimension
|
|
71047
|
+
: (Array.isArray(value) ? value.length : 1);
|
|
71048
|
+
if (valueDim !== this._originalDimension && valueDim !== 1){
|
|
71049
|
+
dimensionMismatchError(
|
|
71050
|
+
this._originalDimension,
|
|
71051
|
+
valueDim,
|
|
71052
|
+
this._originalIdentifier
|
|
71053
|
+
);
|
|
71054
|
+
}
|
|
70449
71055
|
// Create a variable node for the target (the varying variable)
|
|
70450
71056
|
const { id: targetVarID } = variableNode(
|
|
70451
71057
|
this.strandsContext,
|
|
@@ -70498,6 +71104,16 @@ class StrandsNode {
|
|
|
70498
71104
|
|
|
70499
71105
|
// For varying variables, create swizzle assignment
|
|
70500
71106
|
if (this._originalIdentifier) {
|
|
71107
|
+
const valueDim = value?.isStrandsNode
|
|
71108
|
+
? value.dimension
|
|
71109
|
+
: (Array.isArray(value) ? value.length : 1);
|
|
71110
|
+
if (valueDim !== swizzlePattern.length && valueDim !== 1){
|
|
71111
|
+
dimensionMismatchError(
|
|
71112
|
+
swizzlePattern.length,
|
|
71113
|
+
valueDim,
|
|
71114
|
+
`${this._originalIdentifier}.${swizzlePattern}`
|
|
71115
|
+
);
|
|
71116
|
+
}
|
|
70501
71117
|
// Create a variable node for the target with swizzle
|
|
70502
71118
|
const { id: targetVarID } = variableNode(
|
|
70503
71119
|
this.strandsContext,
|
|
@@ -71046,38 +71662,24 @@ function castToFloat(strandsContext, dep) {
|
|
|
71046
71662
|
return createStrandsNode(id, dimension, strandsContext);
|
|
71047
71663
|
}
|
|
71048
71664
|
|
|
71049
|
-
function structConstructorNode(strandsContext, structTypeInfo,
|
|
71665
|
+
function structConstructorNode(strandsContext, structTypeInfo, dependsOn) {
|
|
71050
71666
|
const { cfg, dag } = strandsContext;
|
|
71051
71667
|
const { properties } = structTypeInfo;
|
|
71052
71668
|
|
|
71053
|
-
if (
|
|
71669
|
+
if (dependsOn.length !== properties.length) {
|
|
71054
71670
|
userError('type error',
|
|
71055
|
-
`You've tried to construct a ${structTypeInfo.typeName} struct with ${
|
|
71671
|
+
`You've tried to construct a ${structTypeInfo.typeName} struct with ${dependsOn.length} properties, but it expects ${properties.length} properties.\n` +
|
|
71056
71672
|
`The properties it expects are:\n` +
|
|
71057
|
-
`${properties.map(prop => prop.name
|
|
71673
|
+
`${properties.map(prop => `${prop.name}: ${prop.dataType.baseType}${prop.dataType.dimension}`).join(', ')}`
|
|
71058
71674
|
);
|
|
71059
71675
|
}
|
|
71060
71676
|
|
|
71061
|
-
const dependsOn = [];
|
|
71062
|
-
for (let i = 0; i < properties.length; i++) {
|
|
71063
|
-
const expectedProperty = properties[i];
|
|
71064
|
-
const { originalNodeID, mappedDependencies } = mapPrimitiveDepsToIDs(strandsContext, expectedProperty.dataType, rawUserArgs[i]);
|
|
71065
|
-
if (originalNodeID) {
|
|
71066
|
-
dependsOn.push(originalNodeID);
|
|
71067
|
-
}
|
|
71068
|
-
else {
|
|
71069
|
-
dependsOn.push(
|
|
71070
|
-
constructTypeFromIDs(strandsContext, expectedProperty.dataType, mappedDependencies)
|
|
71071
|
-
);
|
|
71072
|
-
}
|
|
71073
|
-
}
|
|
71074
|
-
|
|
71075
71677
|
const nodeData = createNodeData({
|
|
71076
71678
|
nodeType: NodeType.OPERATION,
|
|
71077
71679
|
opCode: OpCode.Nary.CONSTRUCTOR,
|
|
71078
71680
|
dimension: properties.length,
|
|
71079
|
-
baseType: structTypeInfo.typeName
|
|
71080
|
-
dependsOn
|
|
71681
|
+
baseType: structTypeInfo.typeName,
|
|
71682
|
+
dependsOn,
|
|
71081
71683
|
});
|
|
71082
71684
|
const id = getOrCreateNode(dag, nodeData);
|
|
71083
71685
|
recordInBasicBlock(cfg, cfg.currentBlock, id);
|
|
@@ -71274,7 +71876,11 @@ function swizzleTrap(id, dimension, strandsContext, onRebind) {
|
|
|
71274
71876
|
scalars.push(createStrandsNode(id, dimension, strandsContext));
|
|
71275
71877
|
}
|
|
71276
71878
|
} else {
|
|
71277
|
-
|
|
71879
|
+
dimensionMismatchError(
|
|
71880
|
+
chars.length,
|
|
71881
|
+
value.dimension,
|
|
71882
|
+
`${target._originalIdentifier || 'value'}.${property}`
|
|
71883
|
+
);
|
|
71278
71884
|
}
|
|
71279
71885
|
} else if (Array.isArray(value)) {
|
|
71280
71886
|
const flat = value.flat(Infinity);
|
|
@@ -71748,7 +72354,7 @@ const glslBackend = {
|
|
|
71748
72354
|
}
|
|
71749
72355
|
const dag = strandsContext.dag;
|
|
71750
72356
|
const rootNode = getNodeDataFromID(dag, rootNodeID);
|
|
71751
|
-
if (isStructType(returnType)) {
|
|
72357
|
+
if (isStructType(returnType) && rootNode.identifier) {
|
|
71752
72358
|
const structTypeInfo = returnType;
|
|
71753
72359
|
for (let i = 0; i < structTypeInfo.properties.length; i++) {
|
|
71754
72360
|
const prop = structTypeInfo.properties[i];
|
|
@@ -72039,7 +72645,7 @@ class FilterRenderer2D {
|
|
|
72039
72645
|
_arraysEqual: (a, b) => JSON.stringify(a) === JSON.stringify(b),
|
|
72040
72646
|
_getEmptyTexture: () => {
|
|
72041
72647
|
if (!this._emptyTexture) {
|
|
72042
|
-
const im = new Image(1, 1);
|
|
72648
|
+
const im = new Image$1(1, 1);
|
|
72043
72649
|
im.set(0, 0, 255);
|
|
72044
72650
|
this._emptyTexture = new Texture(this._renderer, im);
|
|
72045
72651
|
}
|
|
@@ -72471,8 +73077,6 @@ class FilterRenderer2D {
|
|
|
72471
73077
|
}
|
|
72472
73078
|
}
|
|
72473
73079
|
|
|
72474
|
-
const styleEmpty = 'rgba(0,0,0,0)';
|
|
72475
|
-
|
|
72476
73080
|
class Renderer2D extends Renderer {
|
|
72477
73081
|
constructor(pInst, w, h, isMainCanvas, elt, attributes = {}) {
|
|
72478
73082
|
super(pInst, w, h, isMainCanvas);
|
|
@@ -72631,7 +73235,7 @@ class Renderer2D extends Renderer {
|
|
|
72631
73235
|
}
|
|
72632
73236
|
this.push();
|
|
72633
73237
|
this.resetMatrix();
|
|
72634
|
-
if (args[0] instanceof Image) {
|
|
73238
|
+
if (args[0] instanceof Image$1) {
|
|
72635
73239
|
const img = args[0];
|
|
72636
73240
|
if (args[1] >= 0) {
|
|
72637
73241
|
// set transparency of background
|
|
@@ -72904,10 +73508,12 @@ class Renderer2D extends Renderer {
|
|
|
72904
73508
|
ctx.save();
|
|
72905
73509
|
ctx.clearRect(0, 0, img.canvas.width, img.canvas.height);
|
|
72906
73510
|
|
|
73511
|
+
const tint = this.states.tint._getRGBA([255, 255, 255, 255]);
|
|
73512
|
+
|
|
72907
73513
|
if (
|
|
72908
|
-
|
|
72909
|
-
|
|
72910
|
-
|
|
73514
|
+
tint[0] < 255 ||
|
|
73515
|
+
tint[1] < 255 ||
|
|
73516
|
+
tint[2] < 255
|
|
72911
73517
|
) {
|
|
72912
73518
|
// Color tint: we need to use the multiply blend mode to change the colors.
|
|
72913
73519
|
// However, the canvas implementation of this destroys the alpha channel of
|
|
@@ -72930,16 +73536,16 @@ class Renderer2D extends Renderer {
|
|
|
72930
73536
|
|
|
72931
73537
|
// Apply color tint
|
|
72932
73538
|
ctx.globalCompositeOperation = 'multiply';
|
|
72933
|
-
ctx.fillStyle = `rgb(${
|
|
73539
|
+
ctx.fillStyle = `rgb(${tint.slice(0, 3).join(', ')})`;
|
|
72934
73540
|
ctx.fillRect(0, 0, img.canvas.width, img.canvas.height);
|
|
72935
73541
|
|
|
72936
73542
|
// Replace the alpha channel with the original alpha * the alpha tint
|
|
72937
73543
|
ctx.globalCompositeOperation = 'destination-in';
|
|
72938
|
-
ctx.globalAlpha =
|
|
73544
|
+
ctx.globalAlpha = tint[3] / 255;
|
|
72939
73545
|
ctx.drawImage(img.canvas, 0, 0);
|
|
72940
73546
|
} else {
|
|
72941
73547
|
// If we only need to change the alpha, we can skip all the extra work!
|
|
72942
|
-
ctx.globalAlpha =
|
|
73548
|
+
ctx.globalAlpha = tint[3] / 255;
|
|
72943
73549
|
ctx.drawImage(img.canvas, 0, 0);
|
|
72944
73550
|
}
|
|
72945
73551
|
|
|
@@ -73025,7 +73631,7 @@ class Renderer2D extends Renderer {
|
|
|
73025
73631
|
// round down to get integer numbers
|
|
73026
73632
|
x = Math.floor(x);
|
|
73027
73633
|
y = Math.floor(y);
|
|
73028
|
-
if (imgOrCol instanceof Graphics || imgOrCol instanceof Image) {
|
|
73634
|
+
if (imgOrCol instanceof Graphics || imgOrCol instanceof Image$1) {
|
|
73029
73635
|
this.drawingContext.save();
|
|
73030
73636
|
this.drawingContext.setTransform(1, 0, 0, 1, 0, 0);
|
|
73031
73637
|
this.drawingContext.scale(
|
|
@@ -73165,96 +73771,32 @@ class Renderer2D extends Renderer {
|
|
|
73165
73771
|
}
|
|
73166
73772
|
|
|
73167
73773
|
line(x1, y1, x2, y2) {
|
|
73168
|
-
const
|
|
73169
|
-
|
|
73170
|
-
|
|
73171
|
-
|
|
73172
|
-
|
|
73173
|
-
}
|
|
73174
|
-
if (this._clipping) {
|
|
73175
|
-
const tempPath = new Path2D();
|
|
73176
|
-
tempPath.moveTo(x1, y1);
|
|
73177
|
-
tempPath.lineTo(x2, y2);
|
|
73178
|
-
const currentTransform = this.drawingContext.getTransform();
|
|
73179
|
-
const clipBaseTransform = this._clipBaseTransform.inverse();
|
|
73180
|
-
const relativeTransform = clipBaseTransform.multiply(currentTransform);
|
|
73181
|
-
this.clipPath.addPath(tempPath, relativeTransform);
|
|
73182
|
-
return this;
|
|
73183
|
-
}
|
|
73184
|
-
ctx.beginPath();
|
|
73185
|
-
ctx.moveTo(x1, y1);
|
|
73186
|
-
ctx.lineTo(x2, y2);
|
|
73187
|
-
ctx.stroke();
|
|
73774
|
+
const shape = new p5$2.Shape({ position: new p5$2.Vector(0, 0) });
|
|
73775
|
+
shape.beginShape();
|
|
73776
|
+
shape.line(x1, y1, x2, y2);
|
|
73777
|
+
shape.endShape();
|
|
73778
|
+
this.drawShape(shape);
|
|
73188
73779
|
|
|
73189
73780
|
return this;
|
|
73190
73781
|
}
|
|
73191
73782
|
|
|
73192
73783
|
point(x, y) {
|
|
73193
|
-
const
|
|
73194
|
-
|
|
73195
|
-
|
|
73196
|
-
|
|
73197
|
-
|
|
73198
|
-
}
|
|
73199
|
-
const s = this._getStroke();
|
|
73200
|
-
const f = this._getFill();
|
|
73201
|
-
if (this._clipping) {
|
|
73202
|
-
const tempPath = new Path2D();
|
|
73203
|
-
const drawingContextWidth = this.drawingContext.lineWidth;
|
|
73204
|
-
tempPath.arc(x, y, drawingContextWidth / 2, 0, TWO_PI);
|
|
73205
|
-
const currentTransform = this.drawingContext.getTransform();
|
|
73206
|
-
const clipBaseTransform = this._clipBaseTransform.inverse();
|
|
73207
|
-
const relativeTransform = clipBaseTransform.multiply(currentTransform);
|
|
73208
|
-
this.clipPath.addPath(tempPath, relativeTransform);
|
|
73209
|
-
return this;
|
|
73210
|
-
}
|
|
73211
|
-
this._setFill(s);
|
|
73212
|
-
ctx.beginPath();
|
|
73213
|
-
ctx.arc(x, y, ctx.lineWidth / 2, 0, TWO_PI, false);
|
|
73214
|
-
ctx.fill();
|
|
73215
|
-
this._setFill(f);
|
|
73784
|
+
const shape = new p5$2.Shape({ position: new p5$2.Vector(0, 0) });
|
|
73785
|
+
shape.beginShape();
|
|
73786
|
+
shape.point(x, y);
|
|
73787
|
+
shape.endShape();
|
|
73788
|
+
this.drawShape(shape);
|
|
73216
73789
|
|
|
73217
73790
|
return this;
|
|
73218
73791
|
}
|
|
73219
73792
|
|
|
73220
73793
|
quad(x1, y1, x2, y2, x3, y3, x4, y4) {
|
|
73221
|
-
const
|
|
73222
|
-
|
|
73223
|
-
|
|
73224
|
-
|
|
73225
|
-
|
|
73226
|
-
|
|
73227
|
-
}
|
|
73228
|
-
} else if (!doFill && doStroke) {
|
|
73229
|
-
if (this._getStroke() === styleEmpty) {
|
|
73230
|
-
return this;
|
|
73231
|
-
}
|
|
73232
|
-
}
|
|
73233
|
-
if (this._clipping) {
|
|
73234
|
-
const tempPath = new Path2D();
|
|
73235
|
-
tempPath.moveTo(x1, y1);
|
|
73236
|
-
tempPath.lineTo(x2, y2);
|
|
73237
|
-
tempPath.lineTo(x3, y3);
|
|
73238
|
-
tempPath.lineTo(x4, y4);
|
|
73239
|
-
tempPath.closePath();
|
|
73240
|
-
const currentTransform = this.drawingContext.getTransform();
|
|
73241
|
-
const clipBaseTransform = this._clipBaseTransform.inverse();
|
|
73242
|
-
const relativeTransform = clipBaseTransform.multiply(currentTransform);
|
|
73243
|
-
this.clipPath.addPath(tempPath, relativeTransform);
|
|
73244
|
-
return this;
|
|
73245
|
-
}
|
|
73246
|
-
ctx.beginPath();
|
|
73247
|
-
ctx.moveTo(x1, y1);
|
|
73248
|
-
ctx.lineTo(x2, y2);
|
|
73249
|
-
ctx.lineTo(x3, y3);
|
|
73250
|
-
ctx.lineTo(x4, y4);
|
|
73251
|
-
ctx.closePath();
|
|
73252
|
-
if (doFill) {
|
|
73253
|
-
ctx.fill();
|
|
73254
|
-
}
|
|
73255
|
-
if (doStroke) {
|
|
73256
|
-
ctx.stroke();
|
|
73257
|
-
}
|
|
73794
|
+
const shape = new p5$2.Shape({ position: new p5$2.Vector(0, 0) });
|
|
73795
|
+
shape.beginShape();
|
|
73796
|
+
shape.quad(x1, y1, x2, y2, x3, y3, x4, y4);
|
|
73797
|
+
shape.endShape();
|
|
73798
|
+
this.drawShape(shape);
|
|
73799
|
+
|
|
73258
73800
|
return this;
|
|
73259
73801
|
}
|
|
73260
73802
|
|
|
@@ -73267,134 +73809,29 @@ class Renderer2D extends Renderer {
|
|
|
73267
73809
|
let tr = args[5];
|
|
73268
73810
|
let br = args[6];
|
|
73269
73811
|
let bl = args[7];
|
|
73270
|
-
const ctx = this.drawingContext;
|
|
73271
|
-
const doFill = !!this.states.fillColor,
|
|
73272
|
-
doStroke = this.states.strokeColor;
|
|
73273
|
-
if (doFill && !doStroke) {
|
|
73274
|
-
if (this._getFill() === styleEmpty) {
|
|
73275
|
-
return this;
|
|
73276
|
-
}
|
|
73277
|
-
} else if (!doFill && doStroke) {
|
|
73278
|
-
if (this._getStroke() === styleEmpty) {
|
|
73279
|
-
return this;
|
|
73280
|
-
}
|
|
73281
|
-
}
|
|
73282
|
-
if (this._clipping) {
|
|
73283
|
-
const tempPath = new Path2D();
|
|
73284
|
-
if (typeof tl === 'undefined') {
|
|
73285
|
-
tempPath.rect(x, y, w, h);
|
|
73286
|
-
} else {
|
|
73287
|
-
tempPath.roundRect(x, y, w, h, [tl, tr, br, bl]);
|
|
73288
|
-
}
|
|
73289
|
-
const currentTransform = this.drawingContext.getTransform();
|
|
73290
|
-
const clipBaseTransform = this._clipBaseTransform.inverse();
|
|
73291
|
-
const relativeTransform = clipBaseTransform.multiply(currentTransform);
|
|
73292
|
-
this.clipPath.addPath(tempPath, relativeTransform);
|
|
73293
|
-
return this;
|
|
73294
|
-
}
|
|
73295
|
-
ctx.beginPath();
|
|
73296
|
-
if (typeof tl === 'undefined') {
|
|
73297
|
-
// No rounded corners
|
|
73298
|
-
ctx.rect(x, y, w, h);
|
|
73299
|
-
} else {
|
|
73300
|
-
// At least one rounded corner
|
|
73301
|
-
// Set defaults when not specified
|
|
73302
|
-
if (typeof tr === 'undefined') {
|
|
73303
|
-
tr = tl;
|
|
73304
|
-
}
|
|
73305
|
-
if (typeof br === 'undefined') {
|
|
73306
|
-
br = tr;
|
|
73307
|
-
}
|
|
73308
|
-
if (typeof bl === 'undefined') {
|
|
73309
|
-
bl = br;
|
|
73310
|
-
}
|
|
73311
73812
|
|
|
73312
|
-
|
|
73313
|
-
|
|
73314
|
-
|
|
73315
|
-
|
|
73316
|
-
|
|
73317
|
-
|
|
73318
|
-
// Clip radii
|
|
73319
|
-
if (absW < 2 * tl) {
|
|
73320
|
-
tl = hw;
|
|
73321
|
-
}
|
|
73322
|
-
if (absH < 2 * tl) {
|
|
73323
|
-
tl = hh;
|
|
73324
|
-
}
|
|
73325
|
-
if (absW < 2 * tr) {
|
|
73326
|
-
tr = hw;
|
|
73327
|
-
}
|
|
73328
|
-
if (absH < 2 * tr) {
|
|
73329
|
-
tr = hh;
|
|
73330
|
-
}
|
|
73331
|
-
if (absW < 2 * br) {
|
|
73332
|
-
br = hw;
|
|
73333
|
-
}
|
|
73334
|
-
if (absH < 2 * br) {
|
|
73335
|
-
br = hh;
|
|
73336
|
-
}
|
|
73337
|
-
if (absW < 2 * bl) {
|
|
73338
|
-
bl = hw;
|
|
73339
|
-
}
|
|
73340
|
-
if (absH < 2 * bl) {
|
|
73341
|
-
bl = hh;
|
|
73342
|
-
}
|
|
73813
|
+
const shape = new p5$2.Shape({ position: new p5$2.Vector(0, 0) });
|
|
73814
|
+
shape.beginShape();
|
|
73815
|
+
shape.rectPrimitive(x, y, w, h, tl, tr, br, bl);
|
|
73816
|
+
shape.endShape();
|
|
73817
|
+
this.drawShape(shape);
|
|
73343
73818
|
|
|
73344
|
-
ctx.roundRect(x, y, w, h, [tl, tr, br, bl]);
|
|
73345
|
-
}
|
|
73346
|
-
if (doFill) {
|
|
73347
|
-
ctx.fill();
|
|
73348
|
-
}
|
|
73349
|
-
if (doStroke) {
|
|
73350
|
-
ctx.stroke();
|
|
73351
|
-
}
|
|
73352
73819
|
return this;
|
|
73353
73820
|
}
|
|
73354
73821
|
|
|
73355
|
-
|
|
73356
73822
|
triangle(args) {
|
|
73357
|
-
const ctx = this.drawingContext;
|
|
73358
|
-
const doFill = !!this.states.fillColor,
|
|
73359
|
-
doStroke = this.states.strokeColor;
|
|
73360
73823
|
const x1 = args[0],
|
|
73361
73824
|
y1 = args[1];
|
|
73362
73825
|
const x2 = args[2],
|
|
73363
73826
|
y2 = args[3];
|
|
73364
73827
|
const x3 = args[4],
|
|
73365
73828
|
y3 = args[5];
|
|
73366
|
-
|
|
73367
|
-
|
|
73368
|
-
|
|
73369
|
-
|
|
73370
|
-
|
|
73371
|
-
|
|
73372
|
-
return this;
|
|
73373
|
-
}
|
|
73374
|
-
}
|
|
73375
|
-
if (this._clipping) {
|
|
73376
|
-
const tempPath = new Path2D();
|
|
73377
|
-
tempPath.moveTo(x1, y1);
|
|
73378
|
-
tempPath.lineTo(x2, y2);
|
|
73379
|
-
tempPath.lineTo(x3, y3);
|
|
73380
|
-
tempPath.closePath();
|
|
73381
|
-
const currentTransform = this.drawingContext.getTransform();
|
|
73382
|
-
const clipBaseTransform = this._clipBaseTransform.inverse();
|
|
73383
|
-
const relativeTransform = clipBaseTransform.multiply(currentTransform);
|
|
73384
|
-
this.clipPath.addPath(tempPath, relativeTransform);
|
|
73385
|
-
return this;
|
|
73386
|
-
}
|
|
73387
|
-
ctx.beginPath();
|
|
73388
|
-
ctx.moveTo(x1, y1);
|
|
73389
|
-
ctx.lineTo(x2, y2);
|
|
73390
|
-
ctx.lineTo(x3, y3);
|
|
73391
|
-
ctx.closePath();
|
|
73392
|
-
if (doFill) {
|
|
73393
|
-
ctx.fill();
|
|
73394
|
-
}
|
|
73395
|
-
if (doStroke) {
|
|
73396
|
-
ctx.stroke();
|
|
73397
|
-
}
|
|
73829
|
+
|
|
73830
|
+
const shape = new p5$2.Shape({ position: new p5$2.Vector(0, 0) });
|
|
73831
|
+
shape.beginShape();
|
|
73832
|
+
shape.triangle(x1, y1, x2, y2, x3, y3);
|
|
73833
|
+
shape.endShape();
|
|
73834
|
+
this.drawShape(shape);
|
|
73398
73835
|
|
|
73399
73836
|
return this;
|
|
73400
73837
|
}
|
|
@@ -102727,6 +103164,7 @@ function pointer(p5, fn, lifecycles){
|
|
|
102727
103164
|
const events = [
|
|
102728
103165
|
'pointerdown',
|
|
102729
103166
|
'pointerup',
|
|
103167
|
+
'pointercancel',
|
|
102730
103168
|
'pointermove',
|
|
102731
103169
|
'dragend',
|
|
102732
103170
|
'dragover',
|
|
@@ -103786,6 +104224,10 @@ function pointer(p5, fn, lifecycles){
|
|
|
103786
104224
|
this._activePointers.set(e.pointerId, e);
|
|
103787
104225
|
this._setMouseButton(e);
|
|
103788
104226
|
|
|
104227
|
+
if (this.mouseIsPressed && e.buttons === 0) {
|
|
104228
|
+
this._onpointerup(e);
|
|
104229
|
+
}
|
|
104230
|
+
|
|
103789
104231
|
if (
|
|
103790
104232
|
!this.mouseIsPressed &&
|
|
103791
104233
|
typeof this._customActions.mouseMoved === 'function'
|
|
@@ -104112,6 +104554,16 @@ function pointer(p5, fn, lifecycles){
|
|
|
104112
104554
|
fn._ondragend = fn._onpointerup;
|
|
104113
104555
|
fn._ondragover = fn._onpointermove;
|
|
104114
104556
|
|
|
104557
|
+
fn._onpointercancel = function(e) {
|
|
104558
|
+
this._activePointers.delete(e.pointerId);
|
|
104559
|
+
this._setMouseButton(e);
|
|
104560
|
+
this._updatePointerCoords(e);
|
|
104561
|
+
|
|
104562
|
+
if (this._activePointers.size === 0) {
|
|
104563
|
+
this.mouseIsPressed = false;
|
|
104564
|
+
}
|
|
104565
|
+
};
|
|
104566
|
+
|
|
104115
104567
|
/**
|
|
104116
104568
|
* A function that's called once after a mouse button is pressed and released.
|
|
104117
104569
|
*
|
|
@@ -106344,11 +106796,7 @@ function calculation(p5, fn){
|
|
|
106344
106796
|
* -5 and 5 are both five units away from zero, so calling `abs(-5)` and
|
|
106345
106797
|
* `abs(5)` both return 5. The absolute value of a number is always positive.
|
|
106346
106798
|
*
|
|
106347
|
-
*
|
|
106348
|
-
* @param {Number} n number to compute.
|
|
106349
|
-
* @return {Number} absolute value of given number.
|
|
106350
|
-
*
|
|
106351
|
-
* @example
|
|
106799
|
+
* ```js example
|
|
106352
106800
|
* function setup() {
|
|
106353
106801
|
* createCanvas(100, 100);
|
|
106354
106802
|
*
|
|
@@ -106368,6 +106816,55 @@ function calculation(p5, fn){
|
|
|
106368
106816
|
* // from the middle.
|
|
106369
106817
|
* rect(0, 100 - h, 100, h);
|
|
106370
106818
|
* }
|
|
106819
|
+
* ```
|
|
106820
|
+
*
|
|
106821
|
+
* `abs()` can also be used in shaders with p5.strands. The following example
|
|
106822
|
+
* uses `abs()` to create a mirror effect on the color of a shape.
|
|
106823
|
+
*
|
|
106824
|
+
* ```js example
|
|
106825
|
+
* let myShader;
|
|
106826
|
+
*
|
|
106827
|
+
* function setup() {
|
|
106828
|
+
* createCanvas(100, 100, WEBGL);
|
|
106829
|
+
* myShader = buildColorShader(shaderCallback);
|
|
106830
|
+
* describe('A sphere with colors that fold back like a mirror.');
|
|
106831
|
+
* }
|
|
106832
|
+
*
|
|
106833
|
+
* function shaderCallback() {
|
|
106834
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
106835
|
+
* let t = millis() * 0.001;
|
|
106836
|
+
*
|
|
106837
|
+
* // sin(t) goes between -1 and 1 over time.
|
|
106838
|
+
* let sinVal = sin(t);
|
|
106839
|
+
*
|
|
106840
|
+
* // abs() folds the negative values to positive.
|
|
106841
|
+
* // Now value goes between 0 and 1, creating a mirror effect.
|
|
106842
|
+
* let value = abs(sinVal);
|
|
106843
|
+
*
|
|
106844
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
106845
|
+
* let navy = [0.2, 0.2, 0.8, 1];
|
|
106846
|
+
* let coral = [0.8, 0.2, 0.2, 1];
|
|
106847
|
+
*
|
|
106848
|
+
* finalColor.begin();
|
|
106849
|
+
*
|
|
106850
|
+
* // mix() blends between navy (when value = 0) and coral (when value = 1).
|
|
106851
|
+
* finalColor.set(mix(navy, coral, value));
|
|
106852
|
+
*
|
|
106853
|
+
* finalColor.end();
|
|
106854
|
+
* }
|
|
106855
|
+
*
|
|
106856
|
+
* function draw() {
|
|
106857
|
+
* background(220);
|
|
106858
|
+
* shader(myShader);
|
|
106859
|
+
* noStroke();
|
|
106860
|
+
* sphere(30);
|
|
106861
|
+
* }
|
|
106862
|
+
* ```
|
|
106863
|
+
*
|
|
106864
|
+
* @method abs
|
|
106865
|
+
* @param {Number} n number to compute.
|
|
106866
|
+
* @return {Number} absolute value of given number.
|
|
106867
|
+
*
|
|
106371
106868
|
*/
|
|
106372
106869
|
fn.abs = Math.abs;
|
|
106373
106870
|
|
|
@@ -106378,11 +106875,7 @@ function calculation(p5, fn){
|
|
|
106378
106875
|
* For example, calling `ceil(9.03)` and `ceil(9.97)` both return the value
|
|
106379
106876
|
* 10.
|
|
106380
106877
|
*
|
|
106381
|
-
*
|
|
106382
|
-
* @param {Number} n number to round up.
|
|
106383
|
-
* @return {Integer} rounded up number.
|
|
106384
|
-
*
|
|
106385
|
-
* @example
|
|
106878
|
+
* ```js example
|
|
106386
106879
|
* function setup() {
|
|
106387
106880
|
* createCanvas(100, 100);
|
|
106388
106881
|
*
|
|
@@ -106407,6 +106900,57 @@ function calculation(p5, fn){
|
|
|
106407
106900
|
*
|
|
106408
106901
|
* describe('Two rectangles. The one on the left is dark red and the one on the right is bright red.');
|
|
106409
106902
|
* }
|
|
106903
|
+
* ```
|
|
106904
|
+
*
|
|
106905
|
+
* `ceil()` can also be used in shaders with p5.strands. The following example
|
|
106906
|
+
* uses `ceil()` to create a stepped color effect on a shape.
|
|
106907
|
+
*
|
|
106908
|
+
* ```js example
|
|
106909
|
+
* let myShader;
|
|
106910
|
+
*
|
|
106911
|
+
* function setup() {
|
|
106912
|
+
* createCanvas(100, 100, WEBGL);
|
|
106913
|
+
* myShader = buildColorShader(shaderCallback);
|
|
106914
|
+
* describe('A sphere with stepped color bands.');
|
|
106915
|
+
* }
|
|
106916
|
+
*
|
|
106917
|
+
* function shaderCallback() {
|
|
106918
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
106919
|
+
* let t = millis() * 0.001;
|
|
106920
|
+
*
|
|
106921
|
+
* // sin(t) goes between -1 and 1.
|
|
106922
|
+
* // 0.5 + 0.5 * sin(t) remaps this to the 0 to 1 range.
|
|
106923
|
+
* let sinVal = 0.5 + 0.5 * sin(t);
|
|
106924
|
+
*
|
|
106925
|
+
* // Multiply by 4 then ceil to get the next whole number up.
|
|
106926
|
+
* // Divide by 4 to bring the result back to the 0 to 1 range.
|
|
106927
|
+
* // This creates 4 distinct stepped color levels: 0.25, 0.5, 0.75, 1.
|
|
106928
|
+
* let value = ceil(sinVal * 4) / 4;
|
|
106929
|
+
*
|
|
106930
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
106931
|
+
* let cyan = [0, 0.5, 1, 1];
|
|
106932
|
+
* let orange = [1, 0.5, 0, 1];
|
|
106933
|
+
*
|
|
106934
|
+
* finalColor.begin();
|
|
106935
|
+
*
|
|
106936
|
+
* // mix() blends between cyan (when value = 0) and orange (when value = 1).
|
|
106937
|
+
* // ceil() creates sharp steps between color levels.
|
|
106938
|
+
* finalColor.set(mix(cyan, orange, value));
|
|
106939
|
+
*
|
|
106940
|
+
* finalColor.end();
|
|
106941
|
+
* }
|
|
106942
|
+
*
|
|
106943
|
+
* function draw() {
|
|
106944
|
+
* background(220);
|
|
106945
|
+
* shader(myShader);
|
|
106946
|
+
* noStroke();
|
|
106947
|
+
* sphere(30);
|
|
106948
|
+
* }
|
|
106949
|
+
* ```
|
|
106950
|
+
*
|
|
106951
|
+
* @method ceil
|
|
106952
|
+
* @param {Number} n number to round up.
|
|
106953
|
+
* @return {Integer} rounded up number.
|
|
106410
106954
|
*/
|
|
106411
106955
|
fn.ceil = Math.ceil;
|
|
106412
106956
|
|
|
@@ -106544,11 +107088,7 @@ function calculation(p5, fn){
|
|
|
106544
107088
|
* Calculates the value of Euler's number e (2.71828...) raised to the power
|
|
106545
107089
|
* of a number.
|
|
106546
107090
|
*
|
|
106547
|
-
*
|
|
106548
|
-
* @param {Number} n exponent to raise.
|
|
106549
|
-
* @return {Number} e^n
|
|
106550
|
-
*
|
|
106551
|
-
* @example
|
|
107091
|
+
* ```js example
|
|
106552
107092
|
* function setup() {
|
|
106553
107093
|
* createCanvas(100, 100);
|
|
106554
107094
|
*
|
|
@@ -106572,8 +107112,9 @@ function calculation(p5, fn){
|
|
|
106572
107112
|
*
|
|
106573
107113
|
* describe('A series of circles that grow exponentially from top left to bottom right.');
|
|
106574
107114
|
* }
|
|
107115
|
+
* ```
|
|
106575
107116
|
*
|
|
106576
|
-
*
|
|
107117
|
+
* ```js example
|
|
106577
107118
|
* function setup() {
|
|
106578
107119
|
* createCanvas(100, 100);
|
|
106579
107120
|
*
|
|
@@ -106594,6 +107135,53 @@ function calculation(p5, fn){
|
|
|
106594
107135
|
* // Draw a point.
|
|
106595
107136
|
* point(x, y);
|
|
106596
107137
|
* }
|
|
107138
|
+
* ```
|
|
107139
|
+
*
|
|
107140
|
+
* `exp()` can also be used in shaders with p5.strands. The following example
|
|
107141
|
+
* uses `exp()` to create an accelerating color transition on a shape.
|
|
107142
|
+
*
|
|
107143
|
+
* ```js example
|
|
107144
|
+
* let myShader;
|
|
107145
|
+
*
|
|
107146
|
+
* function setup() {
|
|
107147
|
+
* createCanvas(100, 100, WEBGL);
|
|
107148
|
+
* myShader = buildColorShader(shaderCallback);
|
|
107149
|
+
* describe('A sphere that brightens with accelerating speed.');
|
|
107150
|
+
* }
|
|
107151
|
+
*
|
|
107152
|
+
* function shaderCallback() {
|
|
107153
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.0005 to slow it.
|
|
107154
|
+
* let t = millis() * 0.0005;
|
|
107155
|
+
*
|
|
107156
|
+
* // exp(t) grows slowly at first, then accelerates (exponential growth).
|
|
107157
|
+
* // Multiply by 0.01 to keep it from growing too fast.
|
|
107158
|
+
* // min(..., 1) caps the value at 1 so it doesn't go past white.
|
|
107159
|
+
* let value = min(exp(t) * 0.01, 1);
|
|
107160
|
+
*
|
|
107161
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
107162
|
+
* let darkBlue = [0.1, 0.1, 0.3, 1];
|
|
107163
|
+
* let lightYellow = [1, 1, 0.5, 1];
|
|
107164
|
+
*
|
|
107165
|
+
* finalColor.begin();
|
|
107166
|
+
*
|
|
107167
|
+
* // mix() blends between darkBlue (when value = 0) and lightYellow (when value = 1).
|
|
107168
|
+
* // Because exp() accelerates, the color transition gets faster over time.
|
|
107169
|
+
* finalColor.set(mix(darkBlue, lightYellow, value));
|
|
107170
|
+
*
|
|
107171
|
+
* finalColor.end();
|
|
107172
|
+
* }
|
|
107173
|
+
*
|
|
107174
|
+
* function draw() {
|
|
107175
|
+
* background(220);
|
|
107176
|
+
* shader(myShader);
|
|
107177
|
+
* noStroke();
|
|
107178
|
+
* sphere(30);
|
|
107179
|
+
* }
|
|
107180
|
+
* ```
|
|
107181
|
+
*
|
|
107182
|
+
* @method exp
|
|
107183
|
+
* @param {Number} n exponent to raise.
|
|
107184
|
+
* @return {Number} e^n
|
|
106597
107185
|
*/
|
|
106598
107186
|
fn.exp = Math.exp;
|
|
106599
107187
|
|
|
@@ -106601,11 +107189,7 @@ function calculation(p5, fn){
|
|
|
106601
107189
|
* Calculates the closest integer value that is less than or equal to the
|
|
106602
107190
|
* value of a number.
|
|
106603
107191
|
*
|
|
106604
|
-
*
|
|
106605
|
-
* @param {Number} n number to round down.
|
|
106606
|
-
* @return {Integer} rounded down number.
|
|
106607
|
-
*
|
|
106608
|
-
* @example
|
|
107192
|
+
* ```js example
|
|
106609
107193
|
* function setup() {
|
|
106610
107194
|
* createCanvas(100, 100);
|
|
106611
107195
|
*
|
|
@@ -106628,6 +107212,57 @@ function calculation(p5, fn){
|
|
|
106628
107212
|
*
|
|
106629
107213
|
* describe('Two rectangles. The one on the left is bright red and the one on the right is black.');
|
|
106630
107214
|
* }
|
|
107215
|
+
* ```
|
|
107216
|
+
*
|
|
107217
|
+
* `floor()` can also be used in shaders with p5.strands. The following example
|
|
107218
|
+
* uses `floor()` to create banding effects on a shape.
|
|
107219
|
+
*
|
|
107220
|
+
* ```js example
|
|
107221
|
+
* let myShader;
|
|
107222
|
+
*
|
|
107223
|
+
* function setup() {
|
|
107224
|
+
* createCanvas(100, 100, WEBGL);
|
|
107225
|
+
* myShader = buildColorShader(shaderCallback);
|
|
107226
|
+
* describe('A sphere with posterized color bands.');
|
|
107227
|
+
* }
|
|
107228
|
+
*
|
|
107229
|
+
* function shaderCallback() {
|
|
107230
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
107231
|
+
* let t = millis() * 0.001;
|
|
107232
|
+
*
|
|
107233
|
+
* // sin(t) goes between -1 and 1.
|
|
107234
|
+
* // 0.5 + 0.5 * sin(t) remaps this to the 0 to 1 range.
|
|
107235
|
+
* let sinVal = 0.5 + 0.5 * sin(t);
|
|
107236
|
+
*
|
|
107237
|
+
* // Multiply by 4 then floor to get the next whole number down.
|
|
107238
|
+
* // Divide by 4 to bring the result back to the 0 to 1 range.
|
|
107239
|
+
* // This creates 5 distinct stepped color levels: 0, 0.25, 0.5, 0.75, 1.
|
|
107240
|
+
* let value = floor(sinVal * 4) / 4;
|
|
107241
|
+
*
|
|
107242
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
107243
|
+
* let darkPurple = [0.2, 0, 0.8, 1];
|
|
107244
|
+
* let brightTeal = [0.2, 1, 0.8, 1];
|
|
107245
|
+
*
|
|
107246
|
+
* finalColor.begin();
|
|
107247
|
+
*
|
|
107248
|
+
* // mix() blends between darkPurple (when value = 0) and brightTeal (when value = 1).
|
|
107249
|
+
* // The floor() creates visible banding/posterization in the color.
|
|
107250
|
+
* finalColor.set(mix(darkPurple, brightTeal, value));
|
|
107251
|
+
*
|
|
107252
|
+
* finalColor.end();
|
|
107253
|
+
* }
|
|
107254
|
+
*
|
|
107255
|
+
* function draw() {
|
|
107256
|
+
* background(220);
|
|
107257
|
+
* shader(myShader);
|
|
107258
|
+
* noStroke();
|
|
107259
|
+
* sphere(30);
|
|
107260
|
+
* }
|
|
107261
|
+
* ```
|
|
107262
|
+
*
|
|
107263
|
+
* @method floor
|
|
107264
|
+
* @param {Number} n number to round down.
|
|
107265
|
+
* @return {Integer} rounded down number.
|
|
106631
107266
|
*/
|
|
106632
107267
|
fn.floor = Math.floor;
|
|
106633
107268
|
|
|
@@ -106644,13 +107279,7 @@ function calculation(p5, fn){
|
|
|
106644
107279
|
* number outside of the original interval. For example, calling
|
|
106645
107280
|
* `lerp(0, 10, 1.5)` will return 15.
|
|
106646
107281
|
*
|
|
106647
|
-
*
|
|
106648
|
-
* @param {Number} start first value.
|
|
106649
|
-
* @param {Number} stop second value.
|
|
106650
|
-
* @param {Number} amt number.
|
|
106651
|
-
* @return {Number} lerped value.
|
|
106652
|
-
*
|
|
106653
|
-
* @example
|
|
107282
|
+
* ```js example
|
|
106654
107283
|
* function setup() {
|
|
106655
107284
|
* createCanvas(100, 100);
|
|
106656
107285
|
*
|
|
@@ -106678,8 +107307,9 @@ function calculation(p5, fn){
|
|
|
106678
107307
|
*
|
|
106679
107308
|
* describe('Five points in a horizontal line. The outer points are black and the inner points are gray.');
|
|
106680
107309
|
* }
|
|
107310
|
+
* ```
|
|
106681
107311
|
*
|
|
106682
|
-
*
|
|
107312
|
+
* ```js example
|
|
106683
107313
|
* let x = 50;
|
|
106684
107314
|
* let y = 50;
|
|
106685
107315
|
* let targetX = 50;
|
|
@@ -106709,6 +107339,54 @@ function calculation(p5, fn){
|
|
|
106709
107339
|
* x = mouseX;
|
|
106710
107340
|
* y = mouseY;
|
|
106711
107341
|
* }
|
|
107342
|
+
* ```
|
|
107343
|
+
*
|
|
107344
|
+
* `lerp()` can also be used in shaders with p5.strands, where it maps to the
|
|
107345
|
+
* <a href="#/p5/mix">mix()</a> function in GLSL. The following example
|
|
107346
|
+
* uses `lerp()` to blend colors on a shape over time.
|
|
107347
|
+
*
|
|
107348
|
+
* ```js example
|
|
107349
|
+
* let myShader;
|
|
107350
|
+
*
|
|
107351
|
+
* function setup() {
|
|
107352
|
+
* createCanvas(100, 100, WEBGL);
|
|
107353
|
+
* myShader = buildColorShader(shaderCallback);
|
|
107354
|
+
* describe('A sphere that blends between teal and coral.');
|
|
107355
|
+
* }
|
|
107356
|
+
*
|
|
107357
|
+
* function shaderCallback() {
|
|
107358
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
107359
|
+
* let t = millis() * 0.001;
|
|
107360
|
+
*
|
|
107361
|
+
* // sin(t) goes between -1 and 1 over time.
|
|
107362
|
+
* // 0.5 + 0.5 * sin(t) remaps this to the 0 to 1 range.
|
|
107363
|
+
* let value = 0.5 + 0.5 * sin(t);
|
|
107364
|
+
*
|
|
107365
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
107366
|
+
* let teal = [0, 0.8, 0.8, 1];
|
|
107367
|
+
* let coral = [1, 0.5, 0.3, 1];
|
|
107368
|
+
*
|
|
107369
|
+
* finalColor.begin();
|
|
107370
|
+
*
|
|
107371
|
+
* // lerp() blends teal (when value = 0) and coral (when value = 1).
|
|
107372
|
+
* finalColor.set(lerp(teal, coral, value));
|
|
107373
|
+
*
|
|
107374
|
+
* finalColor.end();
|
|
107375
|
+
* }
|
|
107376
|
+
*
|
|
107377
|
+
* function draw() {
|
|
107378
|
+
* background(220);
|
|
107379
|
+
* shader(myShader);
|
|
107380
|
+
* noStroke();
|
|
107381
|
+
* sphere(30);
|
|
107382
|
+
* }
|
|
107383
|
+
* ```
|
|
107384
|
+
*
|
|
107385
|
+
* @method lerp
|
|
107386
|
+
* @param {Number} start first value.
|
|
107387
|
+
* @param {Number} stop second value.
|
|
107388
|
+
* @param {Number} amt number.
|
|
107389
|
+
* @return {Number} lerped value.
|
|
106712
107390
|
*/
|
|
106713
107391
|
fn.lerp = function(start, stop, amt) {
|
|
106714
107392
|
// p5._validateParameters('lerp', arguments);
|
|
@@ -106721,11 +107399,7 @@ function calculation(p5, fn){
|
|
|
106721
107399
|
* `log()` expects the `n` parameter to be a value greater than 0 because
|
|
106722
107400
|
* the natural logarithm is defined that way.
|
|
106723
107401
|
*
|
|
106724
|
-
*
|
|
106725
|
-
* @param {Number} n number greater than 0.
|
|
106726
|
-
* @return {Number} natural logarithm of n.
|
|
106727
|
-
*
|
|
106728
|
-
* @example
|
|
107402
|
+
* ```js example
|
|
106729
107403
|
* function setup() {
|
|
106730
107404
|
* createCanvas(100, 100);
|
|
106731
107405
|
*
|
|
@@ -106741,8 +107415,9 @@ function calculation(p5, fn){
|
|
|
106741
107415
|
*
|
|
106742
107416
|
* describe('Two white circles. The circle at the top-left is small. The circle at the bottom-right is about five times larger.');
|
|
106743
107417
|
* }
|
|
107418
|
+
* ```
|
|
106744
107419
|
*
|
|
106745
|
-
*
|
|
107420
|
+
* ```js example
|
|
106746
107421
|
* function setup() {
|
|
106747
107422
|
* createCanvas(100, 100);
|
|
106748
107423
|
*
|
|
@@ -106763,6 +107438,53 @@ function calculation(p5, fn){
|
|
|
106763
107438
|
* // Draw a point.
|
|
106764
107439
|
* point(x, y);
|
|
106765
107440
|
* }
|
|
107441
|
+
* ```
|
|
107442
|
+
*
|
|
107443
|
+
* `log()` can also be used in shaders with p5.strands. The following example
|
|
107444
|
+
* uses `log()` to create a decelerating color transition on a shape.
|
|
107445
|
+
*
|
|
107446
|
+
* ```js example
|
|
107447
|
+
* let myShader;
|
|
107448
|
+
*
|
|
107449
|
+
* function setup() {
|
|
107450
|
+
* createCanvas(100, 100, WEBGL);
|
|
107451
|
+
* myShader = buildColorShader(shaderCallback);
|
|
107452
|
+
* describe('A sphere that slowly shifts from purple to yellow.');
|
|
107453
|
+
* }
|
|
107454
|
+
*
|
|
107455
|
+
* function shaderCallback() {
|
|
107456
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
107457
|
+
* let t = millis() * 0.001;
|
|
107458
|
+
*
|
|
107459
|
+
* // log(1 + t * 2) grows at a moderate pace over time.
|
|
107460
|
+
* // Multiply by 0.4 to bring it into the 0 to 1 range.
|
|
107461
|
+
* // min(..., 1) caps the value at 1.
|
|
107462
|
+
* let value = min(log(1 + t * 2) * 0.4, 1);
|
|
107463
|
+
*
|
|
107464
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
107465
|
+
* let purple = [0.5, 0, 0.5, 1];
|
|
107466
|
+
* let yellow = [1, 1, 0, 1];
|
|
107467
|
+
*
|
|
107468
|
+
* finalColor.begin();
|
|
107469
|
+
*
|
|
107470
|
+
* // mix() blends between purple (when value = 0) and yellow (when value = 1).
|
|
107471
|
+
* // Because log() slows down over time, the color transition decelerates.
|
|
107472
|
+
* finalColor.set(mix(purple, yellow, value));
|
|
107473
|
+
*
|
|
107474
|
+
* finalColor.end();
|
|
107475
|
+
* }
|
|
107476
|
+
*
|
|
107477
|
+
* function draw() {
|
|
107478
|
+
* background(220);
|
|
107479
|
+
* shader(myShader);
|
|
107480
|
+
* noStroke();
|
|
107481
|
+
* sphere(30);
|
|
107482
|
+
* }
|
|
107483
|
+
* ```
|
|
107484
|
+
*
|
|
107485
|
+
* @method log
|
|
107486
|
+
* @param {Number} n number greater than 0.
|
|
107487
|
+
* @return {Number} natural logarithm of n.
|
|
106766
107488
|
*/
|
|
106767
107489
|
fn.log = Math.log;
|
|
106768
107490
|
|
|
@@ -106830,16 +107552,7 @@ function calculation(p5, fn){
|
|
|
106830
107552
|
* constrains the remapped value to the target range. For example,
|
|
106831
107553
|
* `map(11, 0, 10, 0, 100, true)` returns 100.
|
|
106832
107554
|
*
|
|
106833
|
-
*
|
|
106834
|
-
* @param {Number} value the value to be remapped.
|
|
106835
|
-
* @param {Number} start1 lower bound of the value's current range.
|
|
106836
|
-
* @param {Number} stop1 upper bound of the value's current range.
|
|
106837
|
-
* @param {Number} start2 lower bound of the value's target range.
|
|
106838
|
-
* @param {Number} stop2 upper bound of the value's target range.
|
|
106839
|
-
* @param {Boolean} [withinBounds] constrain the value to the newly mapped range.
|
|
106840
|
-
* @return {Number} remapped number.
|
|
106841
|
-
*
|
|
106842
|
-
* @example
|
|
107555
|
+
* ```js example
|
|
106843
107556
|
* function setup() {
|
|
106844
107557
|
* createCanvas(100, 100);
|
|
106845
107558
|
*
|
|
@@ -106858,8 +107571,9 @@ function calculation(p5, fn){
|
|
|
106858
107571
|
* // Draw the bottom line.
|
|
106859
107572
|
* line(0, 75, 0, x);
|
|
106860
107573
|
* }
|
|
107574
|
+
* ```
|
|
106861
107575
|
*
|
|
106862
|
-
*
|
|
107576
|
+
* ```js example
|
|
106863
107577
|
* function setup() {
|
|
106864
107578
|
* createCanvas(100, 100);
|
|
106865
107579
|
*
|
|
@@ -106878,6 +107592,58 @@ function calculation(p5, fn){
|
|
|
106878
107592
|
* // Draw the circle.
|
|
106879
107593
|
* circle(50, 50, 20);
|
|
106880
107594
|
* }
|
|
107595
|
+
* ```
|
|
107596
|
+
*
|
|
107597
|
+
* `map()` can also be used in shaders with p5.strands. The following example
|
|
107598
|
+
* uses `map()` to remap time values to color in a shader.
|
|
107599
|
+
*
|
|
107600
|
+
* ```js example
|
|
107601
|
+
* let myShader;
|
|
107602
|
+
*
|
|
107603
|
+
* function setup() {
|
|
107604
|
+
* createCanvas(100, 100, WEBGL);
|
|
107605
|
+
* myShader = buildColorShader(shaderCallback);
|
|
107606
|
+
* describe('A sphere that shifts between cyan and orange over time.');
|
|
107607
|
+
* }
|
|
107608
|
+
*
|
|
107609
|
+
* function shaderCallback() {
|
|
107610
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
107611
|
+
* let t = millis() * 0.001;
|
|
107612
|
+
*
|
|
107613
|
+
* // sin(t) goes between -1 and 1 over time.
|
|
107614
|
+
* let sinVal = sin(t);
|
|
107615
|
+
*
|
|
107616
|
+
* // map() remaps this from the range [-1, 1] to the range [0, 1].
|
|
107617
|
+
* let value = map(sinVal, -1, 1, 0, 1);
|
|
107618
|
+
*
|
|
107619
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
107620
|
+
* let cyan = [0, 0.5, 1, 1];
|
|
107621
|
+
* let orange = [1, 0.5, 0, 1];
|
|
107622
|
+
*
|
|
107623
|
+
* finalColor.begin();
|
|
107624
|
+
*
|
|
107625
|
+
* // mix() blends between cyan (when value = 0) and orange (when value = 1).
|
|
107626
|
+
* finalColor.set(mix(cyan, orange, value));
|
|
107627
|
+
*
|
|
107628
|
+
* finalColor.end();
|
|
107629
|
+
* }
|
|
107630
|
+
*
|
|
107631
|
+
* function draw() {
|
|
107632
|
+
* background(220);
|
|
107633
|
+
* shader(myShader);
|
|
107634
|
+
* noStroke();
|
|
107635
|
+
* sphere(30);
|
|
107636
|
+
* }
|
|
107637
|
+
* ```
|
|
107638
|
+
*
|
|
107639
|
+
* @method map
|
|
107640
|
+
* @param {Number} value the value to be remapped.
|
|
107641
|
+
* @param {Number} start1 lower bound of the value's current range.
|
|
107642
|
+
* @param {Number} stop1 upper bound of the value's current range.
|
|
107643
|
+
* @param {Number} start2 lower bound of the value's target range.
|
|
107644
|
+
* @param {Number} stop2 upper bound of the value's target range.
|
|
107645
|
+
* @param {Boolean} [withinBounds] constrain the value to the newly mapped range.
|
|
107646
|
+
* @return {Number} remapped number.
|
|
106881
107647
|
*/
|
|
106882
107648
|
fn.map = function(n, start1, stop1, start2, stop2, withinBounds) {
|
|
106883
107649
|
// p5._validateParameters('map', arguments);
|
|
@@ -106901,12 +107667,7 @@ function calculation(p5, fn){
|
|
|
106901
107667
|
* The version of `max()` with two or more parameters interprets them as
|
|
106902
107668
|
* individual numbers and returns the largest number.
|
|
106903
107669
|
*
|
|
106904
|
-
*
|
|
106905
|
-
* @param {Number} n0 first number to compare.
|
|
106906
|
-
* @param {Number} n1 second number to compare.
|
|
106907
|
-
* @return {Number} maximum number.
|
|
106908
|
-
*
|
|
106909
|
-
* @example
|
|
107670
|
+
* ```js example
|
|
106910
107671
|
* function setup() {
|
|
106911
107672
|
* createCanvas(100, 100);
|
|
106912
107673
|
*
|
|
@@ -106924,8 +107685,9 @@ function calculation(p5, fn){
|
|
|
106924
107685
|
*
|
|
106925
107686
|
* describe('The number 20 written in the middle of a gray square.');
|
|
106926
107687
|
* }
|
|
107688
|
+
* ```
|
|
106927
107689
|
*
|
|
106928
|
-
*
|
|
107690
|
+
* ```js example
|
|
106929
107691
|
* function setup() {
|
|
106930
107692
|
* createCanvas(100, 100);
|
|
106931
107693
|
*
|
|
@@ -106946,6 +107708,53 @@ function calculation(p5, fn){
|
|
|
106946
107708
|
*
|
|
106947
107709
|
* describe('The number 20 written in the middle of a gray square.');
|
|
106948
107710
|
* }
|
|
107711
|
+
* ```
|
|
107712
|
+
*
|
|
107713
|
+
* `max()` can also be used in shaders with p5.strands. The following example
|
|
107714
|
+
* uses `max()` to clamp values in a shader.
|
|
107715
|
+
*
|
|
107716
|
+
* ```js example
|
|
107717
|
+
* let myShader;
|
|
107718
|
+
*
|
|
107719
|
+
* function setup() {
|
|
107720
|
+
* createCanvas(100, 100, WEBGL);
|
|
107721
|
+
* myShader = buildColorShader(shaderCallback);
|
|
107722
|
+
* describe('A sphere that shifts from rose to steelBlue and stops.');
|
|
107723
|
+
* }
|
|
107724
|
+
*
|
|
107725
|
+
* function shaderCallback() {
|
|
107726
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
107727
|
+
* let t = millis() * 0.001;
|
|
107728
|
+
*
|
|
107729
|
+
* // 1 - t * 0.2 decreases steadily over time.
|
|
107730
|
+
* // max(..., 0) ensures the value never goes below 0.
|
|
107731
|
+
* let value = max(1 - t * 0.2, 0);
|
|
107732
|
+
*
|
|
107733
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
107734
|
+
* let steelBlue = [0, 0.3, 0.8, 1];
|
|
107735
|
+
* let rose = [1, 0.3, 0.8, 1];
|
|
107736
|
+
*
|
|
107737
|
+
* finalColor.begin();
|
|
107738
|
+
*
|
|
107739
|
+
* // mix() blends between steelBlue (when value = 0) and rose (when value = 1).
|
|
107740
|
+
* // max() clamps the blend so the color stops changing once it reaches steelBlue.
|
|
107741
|
+
* finalColor.set(mix(steelBlue, rose, value));
|
|
107742
|
+
*
|
|
107743
|
+
* finalColor.end();
|
|
107744
|
+
* }
|
|
107745
|
+
*
|
|
107746
|
+
* function draw() {
|
|
107747
|
+
* background(220);
|
|
107748
|
+
* shader(myShader);
|
|
107749
|
+
* noStroke();
|
|
107750
|
+
* sphere(30);
|
|
107751
|
+
* }
|
|
107752
|
+
* ```
|
|
107753
|
+
*
|
|
107754
|
+
* @method max
|
|
107755
|
+
* @param {Number} n0 first number to compare.
|
|
107756
|
+
* @param {Number} n1 second number to compare.
|
|
107757
|
+
* @return {Number} maximum number.
|
|
106949
107758
|
*/
|
|
106950
107759
|
/**
|
|
106951
107760
|
* @method max
|
|
@@ -106977,12 +107786,7 @@ function calculation(p5, fn){
|
|
|
106977
107786
|
* The version of `min()` with two or more parameters interprets them as
|
|
106978
107787
|
* individual numbers and returns the smallest number.
|
|
106979
107788
|
*
|
|
106980
|
-
*
|
|
106981
|
-
* @param {Number} n0 first number to compare.
|
|
106982
|
-
* @param {Number} n1 second number to compare.
|
|
106983
|
-
* @return {Number} minimum number.
|
|
106984
|
-
*
|
|
106985
|
-
* @example
|
|
107789
|
+
* ```js example
|
|
106986
107790
|
* function setup() {
|
|
106987
107791
|
* createCanvas(100, 100);
|
|
106988
107792
|
*
|
|
@@ -107000,8 +107804,9 @@ function calculation(p5, fn){
|
|
|
107000
107804
|
*
|
|
107001
107805
|
* describe('The number 5 written in the middle of a gray square.');
|
|
107002
107806
|
* }
|
|
107807
|
+
* ```
|
|
107003
107808
|
*
|
|
107004
|
-
*
|
|
107809
|
+
* ```js example
|
|
107005
107810
|
* function setup() {
|
|
107006
107811
|
* createCanvas(100, 100);
|
|
107007
107812
|
*
|
|
@@ -107022,6 +107827,53 @@ function calculation(p5, fn){
|
|
|
107022
107827
|
*
|
|
107023
107828
|
* describe('The number 5 written in the middle of a gray square.');
|
|
107024
107829
|
* }
|
|
107830
|
+
* ```
|
|
107831
|
+
*
|
|
107832
|
+
* `min()` can also be used in shaders with p5.strands. The following example
|
|
107833
|
+
* uses `min()` to clamp values in a shader.
|
|
107834
|
+
*
|
|
107835
|
+
* ```js example
|
|
107836
|
+
* let myShader;
|
|
107837
|
+
*
|
|
107838
|
+
* function setup() {
|
|
107839
|
+
* createCanvas(100, 100, WEBGL);
|
|
107840
|
+
* myShader = buildColorShader(shaderCallback);
|
|
107841
|
+
* describe('A sphere that shifts from red to green and stops.');
|
|
107842
|
+
* }
|
|
107843
|
+
*
|
|
107844
|
+
* function shaderCallback() {
|
|
107845
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
107846
|
+
* let t = millis() * 0.001;
|
|
107847
|
+
*
|
|
107848
|
+
* // t * 0.2 grows steadily over time.
|
|
107849
|
+
* // min(..., 1) caps the value at 1 so it doesn't go past the target color.
|
|
107850
|
+
* let value = min(t * 0.2, 1);
|
|
107851
|
+
*
|
|
107852
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
107853
|
+
* let deepRed = [0.8, 0, 0.2, 1];
|
|
107854
|
+
* let yellowGreen = [0.8, 1, 0.2, 1];
|
|
107855
|
+
*
|
|
107856
|
+
* finalColor.begin();
|
|
107857
|
+
*
|
|
107858
|
+
* // mix() blends between deepRed (when value = 0) and yellowGreen (when value = 1).
|
|
107859
|
+
* // min() clamps the blend so the color stops changing once it reaches yellowGreen.
|
|
107860
|
+
* finalColor.set(mix(deepRed, yellowGreen, value));
|
|
107861
|
+
*
|
|
107862
|
+
* finalColor.end();
|
|
107863
|
+
* }
|
|
107864
|
+
*
|
|
107865
|
+
* function draw() {
|
|
107866
|
+
* background(220);
|
|
107867
|
+
* shader(myShader);
|
|
107868
|
+
* noStroke();
|
|
107869
|
+
* sphere(30);
|
|
107870
|
+
* }
|
|
107871
|
+
* ```
|
|
107872
|
+
*
|
|
107873
|
+
* @method min
|
|
107874
|
+
* @param {Number} n0 first number to compare.
|
|
107875
|
+
* @param {Number} n1 second number to compare.
|
|
107876
|
+
* @return {Number} minimum number.
|
|
107025
107877
|
*/
|
|
107026
107878
|
/**
|
|
107027
107879
|
* @method min
|
|
@@ -107090,12 +107942,7 @@ function calculation(p5, fn){
|
|
|
107090
107942
|
* 2 × 2 × 2. `pow(2, -3)` evaluates 1 ÷
|
|
107091
107943
|
* (2 × 2 × 2).
|
|
107092
107944
|
*
|
|
107093
|
-
*
|
|
107094
|
-
* @param {Number} n base of the exponential expression.
|
|
107095
|
-
* @param {Number} e power by which to raise the base.
|
|
107096
|
-
* @return {Number} n^e.
|
|
107097
|
-
*
|
|
107098
|
-
* @example
|
|
107945
|
+
* ```js example
|
|
107099
107946
|
* function setup() {
|
|
107100
107947
|
* createCanvas(100, 100);
|
|
107101
107948
|
*
|
|
@@ -107122,6 +107969,52 @@ function calculation(p5, fn){
|
|
|
107122
107969
|
*
|
|
107123
107970
|
* describe('A series of circles that grow exponentially from top left to bottom right.');
|
|
107124
107971
|
* }
|
|
107972
|
+
* ```
|
|
107973
|
+
*
|
|
107974
|
+
* `pow()` can also be used in shaders with p5.strands. The following example
|
|
107975
|
+
* uses `pow()` to create a gamma curve effect on colors in a shader.
|
|
107976
|
+
*
|
|
107977
|
+
* ```js example
|
|
107978
|
+
* let myShader;
|
|
107979
|
+
*
|
|
107980
|
+
* function setup() {
|
|
107981
|
+
* createCanvas(100, 100, WEBGL);
|
|
107982
|
+
* myShader = buildColorShader(shaderCallback);
|
|
107983
|
+
* describe('A sphere with colors that shift with a power curve.');
|
|
107984
|
+
* }
|
|
107985
|
+
*
|
|
107986
|
+
* function shaderCallback() {
|
|
107987
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.0005 to slow it.
|
|
107988
|
+
* let t = millis() * 0.0005;
|
|
107989
|
+
*
|
|
107990
|
+
* // pow(t, 2) squares the time value: it starts slow then accelerates.
|
|
107991
|
+
* let value = pow(t, 2);
|
|
107992
|
+
*
|
|
107993
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
107994
|
+
* let deepBlue = [0, 0.1, 0.5, 1];
|
|
107995
|
+
* let gold = [1, 0.8, 0, 1];
|
|
107996
|
+
*
|
|
107997
|
+
* finalColor.begin();
|
|
107998
|
+
*
|
|
107999
|
+
* // mix() blends between deepBlue (when value = 0) and gold (when value = 1).
|
|
108000
|
+
* // Because pow() accelerates, the color transition gets faster over time.
|
|
108001
|
+
* finalColor.set(mix(deepBlue, gold, value));
|
|
108002
|
+
*
|
|
108003
|
+
* finalColor.end();
|
|
108004
|
+
* }
|
|
108005
|
+
*
|
|
108006
|
+
* function draw() {
|
|
108007
|
+
* background(220);
|
|
108008
|
+
* shader(myShader);
|
|
108009
|
+
* noStroke();
|
|
108010
|
+
* sphere(30);
|
|
108011
|
+
* }
|
|
108012
|
+
* ```
|
|
108013
|
+
*
|
|
108014
|
+
* @method pow
|
|
108015
|
+
* @param {Number} n base of the exponential expression.
|
|
108016
|
+
* @param {Number} e power by which to raise the base.
|
|
108017
|
+
* @return {Number} n^e.
|
|
107125
108018
|
*/
|
|
107126
108019
|
fn.pow = Math.pow;
|
|
107127
108020
|
|
|
@@ -107134,12 +108027,7 @@ function calculation(p5, fn){
|
|
|
107134
108027
|
* decimal places to use when rounding. For example, `round(12.34, 1)` returns
|
|
107135
108028
|
* 12.3. `decimals` is 0 by default.
|
|
107136
108029
|
*
|
|
107137
|
-
*
|
|
107138
|
-
* @param {Number} n number to round.
|
|
107139
|
-
* @param {Number} [decimals] number of decimal places to round to, default is 0.
|
|
107140
|
-
* @return {Integer} rounded number.
|
|
107141
|
-
*
|
|
107142
|
-
* @example
|
|
108030
|
+
* ```js example
|
|
107143
108031
|
* function setup() {
|
|
107144
108032
|
* createCanvas(100, 100);
|
|
107145
108033
|
*
|
|
@@ -107157,8 +108045,9 @@ function calculation(p5, fn){
|
|
|
107157
108045
|
*
|
|
107158
108046
|
* describe('The number 4 written in middle of the canvas.');
|
|
107159
108047
|
* }
|
|
108048
|
+
* ```
|
|
107160
108049
|
*
|
|
107161
|
-
*
|
|
108050
|
+
* ```js example
|
|
107162
108051
|
* function setup() {
|
|
107163
108052
|
* createCanvas(100, 100);
|
|
107164
108053
|
*
|
|
@@ -107176,6 +108065,57 @@ function calculation(p5, fn){
|
|
|
107176
108065
|
*
|
|
107177
108066
|
* describe('The number 12.78 written in middle of canvas.');
|
|
107178
108067
|
* }
|
|
108068
|
+
* ```
|
|
108069
|
+
*
|
|
108070
|
+
* `round()` can also be used in shaders with p5.strands. The following example
|
|
108071
|
+
* uses `round()` to quantize colors in a shader.
|
|
108072
|
+
*
|
|
108073
|
+
* ```js example
|
|
108074
|
+
* let myShader;
|
|
108075
|
+
*
|
|
108076
|
+
* function setup() {
|
|
108077
|
+
* createCanvas(100, 100, WEBGL);
|
|
108078
|
+
* myShader = buildColorShader(shaderCallback);
|
|
108079
|
+
* describe('A sphere with posterized quantized colors.');
|
|
108080
|
+
* }
|
|
108081
|
+
*
|
|
108082
|
+
* function shaderCallback() {
|
|
108083
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
108084
|
+
* let t = millis() * 0.001;
|
|
108085
|
+
*
|
|
108086
|
+
* // sin(t) goes between -1 and 1.
|
|
108087
|
+
* // 0.5 + 0.5 * sin(t) remaps this to the 0 to 1 range.
|
|
108088
|
+
* let sinVal = 0.5 + 0.5 * sin(t);
|
|
108089
|
+
*
|
|
108090
|
+
* // Multiply by 4 then round to get 5 distinct levels (0, 0.25, 0.5, 0.75, 1).
|
|
108091
|
+
* // Divide by 4 to bring the result back to the 0 to 1 range.
|
|
108092
|
+
* let value = round(sinVal * 4) / 4;
|
|
108093
|
+
*
|
|
108094
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
108095
|
+
* let mutedBlue = [0.3, 0.4, 0.7, 1];
|
|
108096
|
+
* let rose = [0.8, 0.3, 0.4, 1];
|
|
108097
|
+
*
|
|
108098
|
+
* finalColor.begin();
|
|
108099
|
+
*
|
|
108100
|
+
* // mix() blends between mutedBlue (when value = 0) and rose (when value = 1).
|
|
108101
|
+
* // The round() creates stepped bands of color like a posterization effect.
|
|
108102
|
+
* finalColor.set(mix(mutedBlue, rose, value));
|
|
108103
|
+
*
|
|
108104
|
+
* finalColor.end();
|
|
108105
|
+
* }
|
|
108106
|
+
*
|
|
108107
|
+
* function draw() {
|
|
108108
|
+
* background(220);
|
|
108109
|
+
* shader(myShader);
|
|
108110
|
+
* noStroke();
|
|
108111
|
+
* sphere(30);
|
|
108112
|
+
* }
|
|
108113
|
+
* ```
|
|
108114
|
+
*
|
|
108115
|
+
* @method round
|
|
108116
|
+
* @param {Number} n number to round.
|
|
108117
|
+
* @param {Number} [decimals] number of decimal places to round to, default is 0.
|
|
108118
|
+
* @return {Integer} rounded number.
|
|
107179
108119
|
*/
|
|
107180
108120
|
fn.round = function(n, decimals) {
|
|
107181
108121
|
if (!decimals) {
|
|
@@ -107246,11 +108186,7 @@ function calculation(p5, fn){
|
|
|
107246
108186
|
* always returns a positive value. `sqrt()` doesn't work with negative arguments
|
|
107247
108187
|
* such as `sqrt(-9)`.
|
|
107248
108188
|
*
|
|
107249
|
-
*
|
|
107250
|
-
* @param {Number} n non-negative number to square root.
|
|
107251
|
-
* @return {Number} square root of number.
|
|
107252
|
-
*
|
|
107253
|
-
* @example
|
|
108189
|
+
* ```js example
|
|
107254
108190
|
* function setup() {
|
|
107255
108191
|
* createCanvas(100, 100);
|
|
107256
108192
|
*
|
|
@@ -107266,8 +108202,9 @@ function calculation(p5, fn){
|
|
|
107266
108202
|
*
|
|
107267
108203
|
* describe('Two white circles. The circle at the top-left is small. The circle at the bottom-right is ten times larger.');
|
|
107268
108204
|
* }
|
|
108205
|
+
* ```
|
|
107269
108206
|
*
|
|
107270
|
-
*
|
|
108207
|
+
* ```js example
|
|
107271
108208
|
* function setup() {
|
|
107272
108209
|
* createCanvas(100, 100);
|
|
107273
108210
|
*
|
|
@@ -107288,6 +108225,63 @@ function calculation(p5, fn){
|
|
|
107288
108225
|
* // Draw the point.
|
|
107289
108226
|
* point(x, y);
|
|
107290
108227
|
* }
|
|
108228
|
+
* ```
|
|
108229
|
+
*
|
|
108230
|
+
* `sqrt()` can also be used in shaders with p5.strands. The following example
|
|
108231
|
+
* uses `sqrt()` to create a smooth ease-out curve on color and size.
|
|
108232
|
+
*
|
|
108233
|
+
* ```js example
|
|
108234
|
+
* let myShader;
|
|
108235
|
+
*
|
|
108236
|
+
* function setup() {
|
|
108237
|
+
* createCanvas(100, 100, WEBGL);
|
|
108238
|
+
* myShader = buildColorShader(shaderCallback);
|
|
108239
|
+
* describe('A sphere that grows and shifts from navy to orange with an ease-out curve.');
|
|
108240
|
+
* }
|
|
108241
|
+
*
|
|
108242
|
+
* function shaderCallback() {
|
|
108243
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
108244
|
+
* let t = millis() * 0.001;
|
|
108245
|
+
*
|
|
108246
|
+
* // sin(t) goes between -1 and 1.
|
|
108247
|
+
* // 0.5 + 0.5 * sin(t) remaps this to the 0 to 1 range.
|
|
108248
|
+
* let sinVal = 0.5 + 0.5 * sin(t);
|
|
108249
|
+
*
|
|
108250
|
+
* // sqrt(sinVal) creates an ease-out curve: fast start, slow finish.
|
|
108251
|
+
* // Since sinVal is in [0,1], sqrt() stays in [0,1].
|
|
108252
|
+
* let value = sqrt(sinVal);
|
|
108253
|
+
*
|
|
108254
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
108255
|
+
* let navy = [0, 0.1, 0.4, 1];
|
|
108256
|
+
* let brightOrange = [1, 0.6, 0, 1];
|
|
108257
|
+
*
|
|
108258
|
+
* finalColor.begin();
|
|
108259
|
+
*
|
|
108260
|
+
* // mix() blends between navy (when value = 0) and brightOrange (when value = 1).
|
|
108261
|
+
* // The sqrt() ease-out makes the color change fast at first, then slow down.
|
|
108262
|
+
* finalColor.set(mix(navy, brightOrange, value));
|
|
108263
|
+
*
|
|
108264
|
+
* finalColor.end();
|
|
108265
|
+
* }
|
|
108266
|
+
*
|
|
108267
|
+
* function drawShape() {
|
|
108268
|
+
* let t = millis() * 0.001;
|
|
108269
|
+
* let sinVal = 0.5 + 0.5 * sin(t);
|
|
108270
|
+
* let size = 10 + sqrt(sinVal) * 30;
|
|
108271
|
+
* sphere(size);
|
|
108272
|
+
* }
|
|
108273
|
+
*
|
|
108274
|
+
* function draw() {
|
|
108275
|
+
* background(220);
|
|
108276
|
+
* shader(myShader);
|
|
108277
|
+
* noStroke();
|
|
108278
|
+
* drawShape();
|
|
108279
|
+
* }
|
|
108280
|
+
* ```
|
|
108281
|
+
*
|
|
108282
|
+
* @method sqrt
|
|
108283
|
+
* @param {Number} n non-negative number to square root.
|
|
108284
|
+
* @return {Number} square root of number.
|
|
107291
108285
|
*/
|
|
107292
108286
|
fn.sqrt = Math.sqrt;
|
|
107293
108287
|
|
|
@@ -107297,11 +108291,7 @@ function calculation(p5, fn){
|
|
|
107297
108291
|
* A number's fractional part includes its decimal values. For example,
|
|
107298
108292
|
* `fract(12.34)` returns 0.34.
|
|
107299
108293
|
*
|
|
107300
|
-
*
|
|
107301
|
-
* @param {Number} n number whose fractional part will be found.
|
|
107302
|
-
* @returns {Number} fractional part of n.
|
|
107303
|
-
*
|
|
107304
|
-
* @example
|
|
108294
|
+
* ```js example
|
|
107305
108295
|
* function setup() {
|
|
107306
108296
|
* createCanvas(100, 100);
|
|
107307
108297
|
*
|
|
@@ -107321,6 +108311,53 @@ function calculation(p5, fn){
|
|
|
107321
108311
|
*
|
|
107322
108312
|
* describe('The number 56.78 written above the number 0.78.');
|
|
107323
108313
|
* }
|
|
108314
|
+
* ```
|
|
108315
|
+
*
|
|
108316
|
+
* `fract()` can also be used in shaders with p5.strands. The following example
|
|
108317
|
+
* uses `fract()` to create repeating patterns in a shader.
|
|
108318
|
+
*
|
|
108319
|
+
* ```js example
|
|
108320
|
+
* let myShader;
|
|
108321
|
+
*
|
|
108322
|
+
* function setup() {
|
|
108323
|
+
* createCanvas(100, 100, WEBGL);
|
|
108324
|
+
* myShader = buildColorShader(shaderCallback);
|
|
108325
|
+
* describe('A sphere with a repeating gradient pattern.');
|
|
108326
|
+
* }
|
|
108327
|
+
*
|
|
108328
|
+
* function shaderCallback() {
|
|
108329
|
+
* // shaderCallback runs on the GPU. millis() gives ms since start; multiply by 0.001 for seconds.
|
|
108330
|
+
* let t = millis() * 0.001;
|
|
108331
|
+
*
|
|
108332
|
+
* // Multiply by 0.5 to slow the animation to half speed.
|
|
108333
|
+
* // fract(t * 0.5) extracts only the decimal part of the number.
|
|
108334
|
+
* // This creates a smooth sawtooth wave that repeats every 2 seconds.
|
|
108335
|
+
* let value = fract(t * 0.5);
|
|
108336
|
+
*
|
|
108337
|
+
* // Each color is [R, G, B, A] with values from 0 to 1.
|
|
108338
|
+
* let cyan = [0, 0.5, 1, 1];
|
|
108339
|
+
* let orange = [1, 0.5, 0, 1];
|
|
108340
|
+
*
|
|
108341
|
+
* finalColor.begin();
|
|
108342
|
+
*
|
|
108343
|
+
* // mix() blends between cyan (when value = 0) and orange (when value = 1).
|
|
108344
|
+
* // Because fract() resets to 0 each cycle, the color loops smoothly.
|
|
108345
|
+
* finalColor.set(mix(cyan, orange, value));
|
|
108346
|
+
*
|
|
108347
|
+
* finalColor.end();
|
|
108348
|
+
* }
|
|
108349
|
+
*
|
|
108350
|
+
* function draw() {
|
|
108351
|
+
* background(220);
|
|
108352
|
+
* shader(myShader);
|
|
108353
|
+
* noStroke();
|
|
108354
|
+
* sphere(30);
|
|
108355
|
+
* }
|
|
108356
|
+
* ```
|
|
108357
|
+
*
|
|
108358
|
+
* @method fract
|
|
108359
|
+
* @param {Number} n number whose fractional part will be found.
|
|
108360
|
+
* @returns {Number} fractional part of n.
|
|
107324
108361
|
*/
|
|
107325
108362
|
fn.fract = function(toConvert) {
|
|
107326
108363
|
// p5._validateParameters('fract', arguments);
|
|
@@ -108452,6 +109489,8 @@ function _validatedVectorOperation(expectsSoloNumberArgument){
|
|
|
108452
109489
|
}
|
|
108453
109490
|
|
|
108454
109491
|
/**
|
|
109492
|
+
* @private
|
|
109493
|
+
* @internal
|
|
108455
109494
|
* Each of the following decorators validates the data on vector operations.
|
|
108456
109495
|
* These ensure that the arguments are consistently formatted, and that
|
|
108457
109496
|
* pre-conditions are met.
|
|
@@ -120921,7 +121960,7 @@ class Font {
|
|
|
120921
121960
|
* coordinates of the bounding box's bottom-left corner. See
|
|
120922
121961
|
* <a href="#/p5/textAlign">textAlign()</a> for more ways to align text.
|
|
120923
121962
|
*
|
|
120924
|
-
* The fourth parameter, `options`, is also optional. `font.
|
|
121963
|
+
* The fourth parameter, `options`, is also optional. `font.textToContours()`
|
|
120925
121964
|
* expects an object with the following properties:
|
|
120926
121965
|
*
|
|
120927
121966
|
* `sampleFactor` is the ratio of the text's path length to the number of
|
|
@@ -121004,6 +122043,15 @@ class Font {
|
|
|
121004
122043
|
*
|
|
121005
122044
|
* The generated model (a Geometry object) can be manipulated further—rotated, scaled,
|
|
121006
122045
|
* or styled with shaders—to create engaging, interactive visual art.
|
|
122046
|
+
*
|
|
122047
|
+
* The `options` parameter is also optional. `font.textToModel()` expects an object
|
|
122048
|
+
* with the following properties:
|
|
122049
|
+
*
|
|
122050
|
+
* `extrude` is the depth to extrude the text. It defaults to 0. A value of 0 produces
|
|
122051
|
+
* flat text; higher values create thicker, 3D models.
|
|
122052
|
+
*
|
|
122053
|
+
* `sampleFactor` is a factor controlling the level of detail for the text contours.
|
|
122054
|
+
* It defaults to 1. Higher values result in smoother curves.
|
|
121007
122055
|
*
|
|
121008
122056
|
* @param {String} str The text string to convert into a 3D model.
|
|
121009
122057
|
* @param {Number} x The x-coordinate for the starting position of the text.
|
|
@@ -124886,7 +125934,7 @@ class RendererGL extends Renderer3D {
|
|
|
124886
125934
|
}
|
|
124887
125935
|
|
|
124888
125936
|
// Create image from data
|
|
124889
|
-
const region = new Image(w * framebuffer.density, h * framebuffer.density);
|
|
125937
|
+
const region = new Image$1(w * framebuffer.density, h * framebuffer.density);
|
|
124890
125938
|
region.imageData = region.canvas.getContext('2d').createImageData(
|
|
124891
125939
|
region.width,
|
|
124892
125940
|
region.height
|
|
@@ -134979,19 +136027,116 @@ function installBuiltinGlobalAccessors(strandsContext) {
|
|
|
134979
136027
|
|
|
134980
136028
|
for (const name of Object.keys(BUILTIN_GLOBAL_SPECS)) {
|
|
134981
136029
|
const spec = BUILTIN_GLOBAL_SPECS[name];
|
|
134982
|
-
|
|
134983
|
-
|
|
136030
|
+
const backingKey = `_strands_${name}`;
|
|
136031
|
+
|
|
136032
|
+
// Define on window for global mode only
|
|
136033
|
+
const inst = getRuntimeP5Instance();
|
|
136034
|
+
if (inst?._isGlobal) {
|
|
136035
|
+
Object.defineProperty(window, name, {
|
|
136036
|
+
get: () => {
|
|
136037
|
+
if (strandsContext.active) {
|
|
136038
|
+
return getBuiltinGlobalNode(strandsContext, name);
|
|
136039
|
+
}
|
|
136040
|
+
const inst = getRuntimeP5Instance();
|
|
136041
|
+
return spec.get(inst);
|
|
136042
|
+
},
|
|
136043
|
+
configurable: true,
|
|
136044
|
+
});
|
|
136045
|
+
}
|
|
136046
|
+
|
|
136047
|
+
// Capture original descriptor (held in closure for the getter to delegate to)
|
|
136048
|
+
const originalProtoDesc = Object.getOwnPropertyDescriptor(strandsContext.p5.prototype, name);
|
|
136049
|
+
|
|
136050
|
+
// Define on p5.prototype for instance mode
|
|
136051
|
+
Object.defineProperty(strandsContext.p5.prototype, name, {
|
|
136052
|
+
get: function() {
|
|
134984
136053
|
if (strandsContext.active) {
|
|
134985
136054
|
return getBuiltinGlobalNode(strandsContext, name);
|
|
134986
136055
|
}
|
|
134987
|
-
|
|
134988
|
-
|
|
136056
|
+
// If our setter stored a value on this instance, return it
|
|
136057
|
+
if (Object.prototype.hasOwnProperty.call(this, backingKey)) {
|
|
136058
|
+
return this[backingKey];
|
|
136059
|
+
}
|
|
136060
|
+
// Delegate to original getter (e.g. width -> this._renderer?.width)
|
|
136061
|
+
if (originalProtoDesc?.get) {
|
|
136062
|
+
return originalProtoDesc.get.call(this);
|
|
136063
|
+
}
|
|
136064
|
+
// Fall back to original value for data properties (like mouseX)
|
|
136065
|
+
return originalProtoDesc?.value;
|
|
134989
136066
|
},
|
|
136067
|
+
set: function(val) {
|
|
136068
|
+
this[backingKey] = val;
|
|
136069
|
+
},
|
|
136070
|
+
configurable: true,
|
|
134990
136071
|
});
|
|
136072
|
+
|
|
136073
|
+
// Define on p5.Graphics.prototype for graphics mode
|
|
136074
|
+
const GraphicsProto = strandsContext.p5?.Graphics?.prototype;
|
|
136075
|
+
if (GraphicsProto) {
|
|
136076
|
+
const originalDesc = Object.getOwnPropertyDescriptor(GraphicsProto, name);
|
|
136077
|
+
|
|
136078
|
+
Object.defineProperty(GraphicsProto, name, {
|
|
136079
|
+
get: function() {
|
|
136080
|
+
if (strandsContext.active) {
|
|
136081
|
+
return getBuiltinGlobalNode(strandsContext, name);
|
|
136082
|
+
}
|
|
136083
|
+
// Delegate to original getter if it exists (class-level getters like width, deltaTime)
|
|
136084
|
+
if (originalDesc?.get) {
|
|
136085
|
+
return originalDesc.get.call(this);
|
|
136086
|
+
}
|
|
136087
|
+
return this[backingKey];
|
|
136088
|
+
},
|
|
136089
|
+
set: function(val) {
|
|
136090
|
+
if (originalDesc?.set) {
|
|
136091
|
+
originalDesc.set.call(this, val);
|
|
136092
|
+
} else {
|
|
136093
|
+
this[backingKey] = val;
|
|
136094
|
+
}
|
|
136095
|
+
},
|
|
136096
|
+
configurable: true,
|
|
136097
|
+
});
|
|
136098
|
+
}
|
|
134991
136099
|
}
|
|
134992
136100
|
strandsContext._builtinGlobalsAccessorsInstalled = true;
|
|
134993
136101
|
}
|
|
134994
136102
|
|
|
136103
|
+
function installInstanceIndexAccessor(strandsContext) {
|
|
136104
|
+
if (strandsContext._instanceIndexAccessorInstalled) return;
|
|
136105
|
+
|
|
136106
|
+
const getRuntimeP5Instance = () => strandsContext.renderer?._pInst || strandsContext.p5?.instance;
|
|
136107
|
+
|
|
136108
|
+
const instanceIndexGetter = function() {
|
|
136109
|
+
if (strandsContext.active) {
|
|
136110
|
+
const node = variableNode(strandsContext, { baseType: BaseType.INT, dimension: 1 }, strandsContext.backend.instanceIdReference());
|
|
136111
|
+
return createStrandsNode(node.id, node.dimension, strandsContext);
|
|
136112
|
+
}
|
|
136113
|
+
return undefined;
|
|
136114
|
+
};
|
|
136115
|
+
|
|
136116
|
+
const inst = getRuntimeP5Instance();
|
|
136117
|
+
if (inst?._isGlobal) {
|
|
136118
|
+
Object.defineProperty(window, 'instanceIndex', {
|
|
136119
|
+
get: instanceIndexGetter,
|
|
136120
|
+
configurable: true,
|
|
136121
|
+
});
|
|
136122
|
+
}
|
|
136123
|
+
|
|
136124
|
+
Object.defineProperty(strandsContext.p5.prototype, 'instanceIndex', {
|
|
136125
|
+
get: instanceIndexGetter,
|
|
136126
|
+
configurable: true,
|
|
136127
|
+
});
|
|
136128
|
+
|
|
136129
|
+
const GraphicsProto = strandsContext.p5?.Graphics?.prototype;
|
|
136130
|
+
if (GraphicsProto) {
|
|
136131
|
+
Object.defineProperty(GraphicsProto, 'instanceIndex', {
|
|
136132
|
+
get: instanceIndexGetter,
|
|
136133
|
+
configurable: true,
|
|
136134
|
+
});
|
|
136135
|
+
}
|
|
136136
|
+
|
|
136137
|
+
strandsContext._instanceIndexAccessorInstalled = true;
|
|
136138
|
+
}
|
|
136139
|
+
|
|
134995
136140
|
//////////////////////////////////////////////
|
|
134996
136141
|
// Prototype mirroring helpers
|
|
134997
136142
|
//////////////////////////////////////////////
|
|
@@ -135165,7 +136310,7 @@ function initGlobalStrandsAPI(p5, fn, strandsContext) {
|
|
|
135165
136310
|
const originalLerp = fn.lerp;
|
|
135166
136311
|
augmentFn(fn, p5, 'lerp', function (...args) {
|
|
135167
136312
|
if (strandsContext.active) {
|
|
135168
|
-
return
|
|
136313
|
+
return this.mix(...args);
|
|
135169
136314
|
} else {
|
|
135170
136315
|
return originalLerp.apply(this, args);
|
|
135171
136316
|
}
|
|
@@ -135188,6 +136333,139 @@ function initGlobalStrandsAPI(p5, fn, strandsContext) {
|
|
|
135188
136333
|
return result;
|
|
135189
136334
|
});
|
|
135190
136335
|
|
|
136336
|
+
const originalColor = fn.color;
|
|
136337
|
+
augmentFn(fn, p5, 'color', function (...args) {
|
|
136338
|
+
if (!strandsContext.active) {
|
|
136339
|
+
return originalColor.apply(this, args);
|
|
136340
|
+
}
|
|
136341
|
+
// Reuse p5's parser - handles hex strings, rgb(), CSS named colors, numerics
|
|
136342
|
+
const c = originalColor.apply(this, args);
|
|
136343
|
+
// _getRGBA() returns [r, g, b, a] normalized to 0-1
|
|
136344
|
+
const rgba = c._getRGBA();
|
|
136345
|
+
const { id, dimension } = primitiveConstructorNode(
|
|
136346
|
+
strandsContext,
|
|
136347
|
+
{ baseType: BaseType.FLOAT, dimension: null },
|
|
136348
|
+
rgba
|
|
136349
|
+
);
|
|
136350
|
+
return createStrandsNode(id, dimension, strandsContext);
|
|
136351
|
+
});
|
|
136352
|
+
const originalLerpColor = fn.lerpColor;
|
|
136353
|
+
augmentFn(fn, p5, 'lerpColor', function (...args) {
|
|
136354
|
+
if (!strandsContext.active) {
|
|
136355
|
+
return originalLerpColor.apply(this, args);
|
|
136356
|
+
}
|
|
136357
|
+
// In strands, colors are vec4s - lerpColor maps directly to GLSL mix()
|
|
136358
|
+
return this.mix(...args);
|
|
136359
|
+
});
|
|
136360
|
+
// Component accessors: extract scalar channels from a vec4 color
|
|
136361
|
+
const originalRed = fn.red;
|
|
136362
|
+
augmentFn(fn, p5, 'red', function (...args) {
|
|
136363
|
+
if (!strandsContext.active) {
|
|
136364
|
+
return originalRed.apply(this, args);
|
|
136365
|
+
}
|
|
136366
|
+
return p5.strandsNode(args[0]).x;
|
|
136367
|
+
});
|
|
136368
|
+
|
|
136369
|
+
const originalGreen = fn.green;
|
|
136370
|
+
augmentFn(fn, p5, 'green', function (...args) {
|
|
136371
|
+
if (!strandsContext.active) {
|
|
136372
|
+
return originalGreen.apply(this, args);
|
|
136373
|
+
}
|
|
136374
|
+
return p5.strandsNode(args[0]).y;
|
|
136375
|
+
});
|
|
136376
|
+
|
|
136377
|
+
const originalBlue = fn.blue;
|
|
136378
|
+
augmentFn(fn, p5, 'blue', function (...args) {
|
|
136379
|
+
if (!strandsContext.active) {
|
|
136380
|
+
return originalBlue.apply(this, args);
|
|
136381
|
+
}
|
|
136382
|
+
return p5.strandsNode(args[0]).z;
|
|
136383
|
+
});
|
|
136384
|
+
|
|
136385
|
+
const originalAlpha = fn.alpha;
|
|
136386
|
+
augmentFn(fn, p5, 'alpha', function (...args) {
|
|
136387
|
+
if (!strandsContext.active) {
|
|
136388
|
+
return originalAlpha.apply(this, args);
|
|
136389
|
+
}
|
|
136390
|
+
return p5.strandsNode(args[0]).w;
|
|
136391
|
+
});
|
|
136392
|
+
|
|
136393
|
+
// RGB to HSB conversion based on:
|
|
136394
|
+
// https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB
|
|
136395
|
+
// Using mix/step to avoid branching, via the compact form from:
|
|
136396
|
+
// http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
|
|
136397
|
+
const _rgb2hsb = (instance, colorNode) => {
|
|
136398
|
+
const r = colorNode.x;
|
|
136399
|
+
const g = colorNode.y;
|
|
136400
|
+
const b = colorNode.z;
|
|
136401
|
+
const K = instance.vec4(0, -1/3, 2/3, -1);
|
|
136402
|
+
const p = instance.mix(
|
|
136403
|
+
instance.vec4(b, g, K.w, K.z),
|
|
136404
|
+
instance.vec4(g, b, K.x, K.y),
|
|
136405
|
+
instance.step(b, g)
|
|
136406
|
+
);
|
|
136407
|
+
const q = instance.mix(
|
|
136408
|
+
instance.vec4(p.x, p.y, p.w, r),
|
|
136409
|
+
instance.vec4(r, p.y, p.z, p.x),
|
|
136410
|
+
instance.step(p.x, r)
|
|
136411
|
+
);
|
|
136412
|
+
const d = q.x.sub(instance.min(q.w, q.y));
|
|
136413
|
+
const e = p5.strandsNode(1e-10);
|
|
136414
|
+
const h = instance.abs(q.z.add(q.w.sub(q.y).div(d.mult(6).add(e))));
|
|
136415
|
+
const s = d.div(q.x.add(e));
|
|
136416
|
+
return instance.vec3(h, s, q.x);
|
|
136417
|
+
};
|
|
136418
|
+
|
|
136419
|
+
const _rgb2hsl = (instance, colorNode) => {
|
|
136420
|
+
const r = colorNode.x;
|
|
136421
|
+
const g = colorNode.y;
|
|
136422
|
+
const b = colorNode.z;
|
|
136423
|
+
const maxC = instance.max(r, instance.max(g, b));
|
|
136424
|
+
const minC = instance.min(r, instance.min(g, b));
|
|
136425
|
+
const l = maxC.add(minC).div(2);
|
|
136426
|
+
const d = maxC.sub(minC);
|
|
136427
|
+
const e = p5.strandsNode(1e-10);
|
|
136428
|
+
const s = instance.mix(
|
|
136429
|
+
p5.strandsNode(0),
|
|
136430
|
+
d.div(p5.strandsNode(1).sub(instance.abs(l.mult(2).sub(1)))),
|
|
136431
|
+
instance.step(e, d)
|
|
136432
|
+
);
|
|
136433
|
+
const h_rg = instance.mod(g.sub(b).div(d.add(e)), p5.strandsNode(6)).div(6);
|
|
136434
|
+
const h_gb = b.sub(r).div(d.add(e)).add(2).div(6);
|
|
136435
|
+
const h_br = r.sub(g).div(d.add(e)).add(4).div(6);
|
|
136436
|
+
const isR = instance.step(maxC.sub(e), r).mult(instance.step(r.sub(e), maxC));
|
|
136437
|
+
const isG = instance.step(maxC.sub(e), g).mult(instance.step(g.sub(e), maxC));
|
|
136438
|
+
const h = instance.mix(instance.mix(h_br, h_gb, isG), h_rg, isR);
|
|
136439
|
+
return instance.vec3(h, s, l);
|
|
136440
|
+
};
|
|
136441
|
+
const originalHue = fn.hue;
|
|
136442
|
+
augmentFn(fn, p5, 'hue', function (...args) {
|
|
136443
|
+
if (!strandsContext.active) return originalHue.apply(this, args);
|
|
136444
|
+
const colorNode = p5.strandsNode(args[0]);
|
|
136445
|
+
return _rgb2hsl(this, this.vec3(colorNode.x, colorNode.y, colorNode.z)).x;
|
|
136446
|
+
});
|
|
136447
|
+
|
|
136448
|
+
const originalSaturation = fn.saturation;
|
|
136449
|
+
augmentFn(fn, p5, 'saturation', function (...args) {
|
|
136450
|
+
if (!strandsContext.active) return originalSaturation.apply(this, args);
|
|
136451
|
+
const colorNode = p5.strandsNode(args[0]);
|
|
136452
|
+
return _rgb2hsl(this, this.vec3(colorNode.x, colorNode.y, colorNode.z)).y;
|
|
136453
|
+
});
|
|
136454
|
+
|
|
136455
|
+
const originalBrightness = fn.brightness;
|
|
136456
|
+
augmentFn(fn, p5, 'brightness', function (...args) {
|
|
136457
|
+
if (!strandsContext.active) return originalBrightness.apply(this, args);
|
|
136458
|
+
const colorNode = p5.strandsNode(args[0]);
|
|
136459
|
+
return _rgb2hsb(this, this.vec3(colorNode.x, colorNode.y, colorNode.z)).z;
|
|
136460
|
+
});
|
|
136461
|
+
|
|
136462
|
+
const originalLightness = fn.lightness;
|
|
136463
|
+
augmentFn(fn, p5, 'lightness', function (...args) {
|
|
136464
|
+
if (!strandsContext.active) return originalLightness.apply(this, args);
|
|
136465
|
+
const colorNode = p5.strandsNode(args[0]);
|
|
136466
|
+
return _rgb2hsl(this, this.vec3(colorNode.x, colorNode.y, colorNode.z)).z;
|
|
136467
|
+
});
|
|
136468
|
+
|
|
135191
136469
|
augmentFn(fn, p5, 'getTexture', function (...rawArgs) {
|
|
135192
136470
|
if (strandsContext.active) {
|
|
135193
136471
|
const { id, dimension } = strandsContext.backend.createGetTextureCall(strandsContext, rawArgs);
|
|
@@ -135213,6 +136491,7 @@ function initGlobalStrandsAPI(p5, fn, strandsContext) {
|
|
|
135213
136491
|
const originalNoise = fn.noise;
|
|
135214
136492
|
const originalNoiseDetail = fn.noiseDetail;
|
|
135215
136493
|
const originalRandom = fn.random;
|
|
136494
|
+
const originalRandomGaussian=fn.randomGaussian;
|
|
135216
136495
|
const originalRandomSeed = fn.randomSeed;
|
|
135217
136496
|
const originalMillis = fn.millis;
|
|
135218
136497
|
|
|
@@ -135356,6 +136635,20 @@ function initGlobalStrandsAPI(p5, fn, strandsContext) {
|
|
|
135356
136635
|
}
|
|
135357
136636
|
});
|
|
135358
136637
|
|
|
136638
|
+
augmentFn(fn, p5, 'randomGaussian', function(...args){
|
|
136639
|
+
if(!strandsContext.active){
|
|
136640
|
+
return originalRandomGaussian.apply(this, args);
|
|
136641
|
+
}
|
|
136642
|
+
const mean = args.length >= 1 ? args[0] : 0;
|
|
136643
|
+
const stdDev = args.length >= 2 ? args[1] : 1;
|
|
136644
|
+
|
|
136645
|
+
const u1 = this.max(this.random(), 1e-6);
|
|
136646
|
+
const u2 = this.random();
|
|
136647
|
+
const z = this.sqrt(this.log(u1).mult(-2)).mult(this.cos(u2.mult(2*Math.PI)));
|
|
136648
|
+
|
|
136649
|
+
return z.mult(stdDev).add(mean);
|
|
136650
|
+
});
|
|
136651
|
+
|
|
135359
136652
|
augmentFn(fn, p5, 'millis', function (...args) {
|
|
135360
136653
|
if (!strandsContext.active) {
|
|
135361
136654
|
return originalMillis.apply(this, args);
|
|
@@ -135547,6 +136840,17 @@ function createHookArguments(strandsContext, parameters){
|
|
|
135547
136840
|
return createStrandsNode(propNode.id, propNode.dimension, strandsContext, onRebind);
|
|
135548
136841
|
},
|
|
135549
136842
|
set(val) {
|
|
136843
|
+
const valDim = val?.isStrandsNode
|
|
136844
|
+
? val.dimension
|
|
136845
|
+
: (Array.isArray(val) ? val.length : 1);
|
|
136846
|
+
if( valDim !== propertyType.dataType.dimension && valDim !== 1){
|
|
136847
|
+
dimensionMismatchError(
|
|
136848
|
+
propertyType.dataType.dimension,
|
|
136849
|
+
valDim,
|
|
136850
|
+
`${param.name}.${propertyType.name}`
|
|
136851
|
+
);
|
|
136852
|
+
}
|
|
136853
|
+
|
|
135550
136854
|
const oldDependsOn = dag.dependsOn[structNode.id];
|
|
135551
136855
|
const newDependsOn = [...oldDependsOn];
|
|
135552
136856
|
let newValueID;
|
|
@@ -135624,6 +136928,7 @@ function enforceReturnTypeMatch(strandsContext, expectedType, returned, hookName
|
|
|
135624
136928
|
}
|
|
135625
136929
|
function createShaderHooksFunctions(strandsContext, fn, shader) {
|
|
135626
136930
|
installBuiltinGlobalAccessors(strandsContext);
|
|
136931
|
+
installInstanceIndexAccessor(strandsContext);
|
|
135627
136932
|
|
|
135628
136933
|
// Add shader context to hooks before spreading
|
|
135629
136934
|
const vertexHooksWithContext = Object.fromEntries(
|
|
@@ -135656,6 +136961,54 @@ function createShaderHooksFunctions(strandsContext, fn, shader) {
|
|
|
135656
136961
|
hook.set = function(result) {
|
|
135657
136962
|
hook._result = result;
|
|
135658
136963
|
};
|
|
136964
|
+
hook._active = false;
|
|
136965
|
+
|
|
136966
|
+
const numStructArgs = hookType.parameters.filter(
|
|
136967
|
+
param => param.type && param.type.properties
|
|
136968
|
+
).length;
|
|
136969
|
+
let argIdx = -1;
|
|
136970
|
+
if (numStructArgs === 1) {
|
|
136971
|
+
argIdx = hookType.parameters.findIndex(
|
|
136972
|
+
param => param.type && param.type.properties
|
|
136973
|
+
);
|
|
136974
|
+
}
|
|
136975
|
+
if (argIdx >= 0) {
|
|
136976
|
+
const structParam = hookType.parameters[argIdx];
|
|
136977
|
+
if (structParam.type.properties) {
|
|
136978
|
+
const nameMatch = /^get([A-Z0-9]\w*)$/.exec(hookType.name);
|
|
136979
|
+
const displayName = nameMatch
|
|
136980
|
+
? nameMatch[1][0].toLowerCase() + nameMatch[1].slice(1)
|
|
136981
|
+
: hookType.name;
|
|
136982
|
+
for (const prop of structParam.type.properties) {
|
|
136983
|
+
const key = prop.name;
|
|
136984
|
+
Object.defineProperty(hook, key, {
|
|
136985
|
+
get() {
|
|
136986
|
+
if (!this._active) {
|
|
136987
|
+
userError(
|
|
136988
|
+
'scope error',
|
|
136989
|
+
`It looks like you're trying to access "${displayName}.${key}" outside of its begin()/end() block.\n\n` +
|
|
136990
|
+
`Properties of ${displayName} are only available between ` +
|
|
136991
|
+
`${displayName}.begin() and ${displayName}.end().\n\n` +
|
|
136992
|
+
`To share data between hooks, use sharedVec3() or sharedFloat() ` +
|
|
136993
|
+
`to pass values between them.`
|
|
136994
|
+
);
|
|
136995
|
+
}
|
|
136996
|
+
return this._args[this._argIdx][key];
|
|
136997
|
+
},
|
|
136998
|
+
set(val) {
|
|
136999
|
+
if (!this._active) {
|
|
137000
|
+
userError(
|
|
137001
|
+
'scope error',
|
|
137002
|
+
`It looks like you're trying to set "${displayName}.${key}" outside of its begin()/end() block.`
|
|
137003
|
+
);
|
|
137004
|
+
}
|
|
137005
|
+
this._args[this._argIdx][key] = val;
|
|
137006
|
+
},
|
|
137007
|
+
enumerable: true,
|
|
137008
|
+
});
|
|
137009
|
+
}
|
|
137010
|
+
}
|
|
137011
|
+
}
|
|
135659
137012
|
|
|
135660
137013
|
let entryBlockID;
|
|
135661
137014
|
function setupHook() {
|
|
@@ -135664,25 +137017,14 @@ function createShaderHooksFunctions(strandsContext, fn, shader) {
|
|
|
135664
137017
|
addEdge(cfg, cfg.currentBlock, entryBlockID);
|
|
135665
137018
|
pushBlock(cfg, entryBlockID);
|
|
135666
137019
|
const args = createHookArguments(strandsContext, hookType.parameters);
|
|
135667
|
-
|
|
135668
|
-
|
|
135669
|
-
|
|
135670
|
-
argIdx = hookType.parameters.findIndex(param => param.type.properties);
|
|
135671
|
-
}
|
|
137020
|
+
hook._active = true;
|
|
137021
|
+
hook._args = args;
|
|
137022
|
+
hook._argIdx = argIdx;
|
|
135672
137023
|
hook._properties = [];
|
|
135673
137024
|
for (let i = 0; i < args.length; i++) {
|
|
135674
137025
|
if (i === argIdx) {
|
|
135675
137026
|
for (const key of args[argIdx].structProperties || []) {
|
|
135676
137027
|
hook._properties.push(key);
|
|
135677
|
-
Object.defineProperty(hook, key, {
|
|
135678
|
-
get() {
|
|
135679
|
-
return args[argIdx][key];
|
|
135680
|
-
},
|
|
135681
|
-
set(val) {
|
|
135682
|
-
args[argIdx][key] = val;
|
|
135683
|
-
},
|
|
135684
|
-
enumerable: true,
|
|
135685
|
-
});
|
|
135686
137028
|
}
|
|
135687
137029
|
if (hookType.returnType?.typeName === hookType.parameters[argIdx].type.typeName) {
|
|
135688
137030
|
hook.set(args[argIdx]);
|
|
@@ -135695,6 +137037,7 @@ function createShaderHooksFunctions(strandsContext, fn, shader) {
|
|
|
135695
137037
|
return args;
|
|
135696
137038
|
}
|
|
135697
137039
|
function finishHook() {
|
|
137040
|
+
hook._active = false;
|
|
135698
137041
|
const userReturned = hook._result;
|
|
135699
137042
|
strandsContext.activeHook = undefined;
|
|
135700
137043
|
|
|
@@ -136133,18 +137476,20 @@ if (typeof p5 !== "undefined") {
|
|
|
136133
137476
|
*/
|
|
136134
137477
|
|
|
136135
137478
|
/**
|
|
136136
|
-
* @
|
|
137479
|
+
* @property instanceIndex
|
|
136137
137480
|
* @beta
|
|
136138
137481
|
* @description
|
|
136139
137482
|
* Returns the index of the current instance when drawing multiple copies of a
|
|
136140
137483
|
* shape with <a href="#/p5/model">`model(count)`</a>. The first instance has an
|
|
136141
|
-
*
|
|
137484
|
+
* index of `0`, the second has `1`, and so on.
|
|
136142
137485
|
*
|
|
136143
137486
|
* This lets each copy of a shape behave differently. For example, you can use
|
|
136144
|
-
* the
|
|
137487
|
+
* the index to place instances at different positions, give them different colors,
|
|
136145
137488
|
* or animate them at different speeds.
|
|
136146
137489
|
*
|
|
136147
|
-
* `
|
|
137490
|
+
* `instanceIndex` can only be used inside a p5.strands shader callback.
|
|
137491
|
+
*
|
|
137492
|
+
* (Note: `instanceID()` is also available as a function for compatibility.)
|
|
136148
137493
|
*
|
|
136149
137494
|
* ```js example
|
|
136150
137495
|
* let instancesShader;
|
|
@@ -136167,7 +137512,7 @@ if (typeof p5 !== "undefined") {
|
|
|
136167
137512
|
* // Spread spheres evenly across the canvas based on their index
|
|
136168
137513
|
* let spacing = width / count;
|
|
136169
137514
|
* worldInputs.position.x +=
|
|
136170
|
-
* (
|
|
137515
|
+
* (instanceIndex - (count - 1) / 2) * spacing;
|
|
136171
137516
|
* worldInputs.end();
|
|
136172
137517
|
* }
|
|
136173
137518
|
*
|
|
@@ -136181,7 +137526,7 @@ if (typeof p5 !== "undefined") {
|
|
|
136181
137526
|
* }
|
|
136182
137527
|
* ```
|
|
136183
137528
|
*
|
|
136184
|
-
* If you are using WebGPU mode, a common pattern is to use `
|
|
137529
|
+
* If you are using WebGPU mode, a common pattern is to use `instanceIndex` to look up data made with
|
|
136185
137530
|
* <a href="#/p5/createStorage">`createStorage()`</a>.
|
|
136186
137531
|
* This lets you give each instance different properties.
|
|
136187
137532
|
*
|
|
@@ -136224,7 +137569,7 @@ if (typeof p5 !== "undefined") {
|
|
|
136224
137569
|
* let itemColor = sharedVec4();
|
|
136225
137570
|
*
|
|
136226
137571
|
* worldInputs.begin();
|
|
136227
|
-
* let item = data[
|
|
137572
|
+
* let item = data[instanceIndex];
|
|
136228
137573
|
* itemColor = item.color;
|
|
136229
137574
|
* worldInputs.position += item.position;
|
|
136230
137575
|
* worldInputs.end();
|
|
@@ -136246,7 +137591,22 @@ if (typeof p5 !== "undefined") {
|
|
|
136246
137591
|
* This can be paired with <a href="#/p5/buildComputeShader">`buildComputeShader`</a>
|
|
136247
137592
|
* to update the data being read.
|
|
136248
137593
|
*
|
|
136249
|
-
* @
|
|
137594
|
+
* @type {*}
|
|
137595
|
+
*/
|
|
137596
|
+
|
|
137597
|
+
/**
|
|
137598
|
+
* @method instanceID
|
|
137599
|
+
* @beta
|
|
137600
|
+
* @deprecated Use <a href="#/p5/instanceIndex">`instanceIndex`</a> instead.
|
|
137601
|
+
* @description
|
|
137602
|
+
* A function alias for <a href="#/p5/instanceIndex">`instanceIndex`</a>, kept for compatibility.
|
|
137603
|
+
* Prefer using <a href="#/p5/instanceIndex">`instanceIndex`</a> directly as a value instead.
|
|
137604
|
+
*
|
|
137605
|
+
* Returns the index of the current instance when drawing multiple copies of a
|
|
137606
|
+
* shape with <a href="#/p5/model">`model(count)`</a>.
|
|
137607
|
+
*
|
|
137608
|
+
* `instanceID()` can only be used inside a p5.strands shader callback.
|
|
137609
|
+
*
|
|
136250
137610
|
* @returns {*} The index of the current instance.
|
|
136251
137611
|
*/
|
|
136252
137612
|
|