Skip to content

Releases: processing/p5.js

v2.0.0

17 Apr 17:06
Compare
Choose a tag to compare

We are releasing p5.js 2.0 to the community for testing and development! Here’s what you need to know.

  • For reference: p5.js 1.x reference will stay on https://p5js.org/, and p5.js 2.x documentation will be on https://beta.p5js.org/
  • In the p5.js Editor: the default will continue to be 1.x until at least August 2026 - more information and discussion on timeline can be found on this Discourse thread or this GitHub thread
  • For updating sketches and add-on libraries: check out the compatibility add-on libraries and guides
  • For contribution: npm latest will default to 2.x, but the git branches are still separated with main on 1.x and dev-2.0 on 2.x. We will switch the branches when we have updated all automations (including deploying updated documentation to the website). Want to contribute ideas or implementation? Check the 2.x project board for an overview of what still needs discussion, and what’s ready for work!

Start exploring 🌱

More details of the changes 🌳

You can also checkout Dave Pagurek's reflections on p5.js 2.0 and an open source philosophy!

Typography

  • A refactor of the typography system to be smaller, support variable fonts, and have more precise text measurement by Daniel Howe @dhowe
  • Support for loading fonts via CSS (thanks to @dhowe)
  • More ways to draw and manipulate text (thanks to @davepagurek)
  • An approximately 350% performance improvement to textToPoints and 3D text extrusion support (thanks to @davepagurek)

Support for more color spaces in p5.Color (thanks to @limzykenneth and @dianamgalindo)

p5.js 2.0 now supports more color modes in addition to the existing RGB, HSB, and HSL color modes. Here are the list of new supported color mode and brief description of them:

  • RGBHDR - High Dynamic Range RGB color defined within the Display P3 color space. You will need to use the HDR canvas described below to draw this color on the canvas accurately.
  • HWB - Hue, Whiteness, Blackness. This is similar to HSL and HSB in that you will define a hue angle however instead of saturation and lightness, you will define the percentage of whiteness and blackness. It is the color model of the GUI color picker used by Chrome.
    color-picker
  • LAB - Also called CIE Lab, defines color with Lightness, Alpha, and Beta. The color space is often used in professional color measuring context.
  • LCH - An easier to use representation of a CIE Lab color with definition of Lightness, Chroma, and Hue instead.
  • OKLAB - OkLab is a slight adjustment to CIE Lab color space mainly to fix a non-uniformity issue that exist in CIE Lab. This difference is more visible in the example below.
  • OKLCH - An easier to use representation of an OkLab color with definition of Lightness, Chroma, and Hue instead.

Comparing HSL, LCH, and OKLCH in a sketch below:
color wheel
From left to right are color wheels of HSL, LCH, and OKLCH respectively. Notice the evenness of color distribution between each wheel with OkLCH having the most even distribution. It can be noted that the LCH wheel has a large blue section that is fixed by OkLCH.

To use these new color spaces in p5.js 2.0, the respective constants have been added and the colorMode() function can be used with these constants in the same way as RGB, HSL, and HSB.

function setup(){
  createCanvas(200, 200);
}

function draw(){
  colorMode(OKLCH);
  background(220); // Should show a teal colored canvas
}

Support for wide-gamut colors with the display-p3 mode (thanks to @limzykenneth)

You can now create a 2D canvas that supports HDR colors that will give you a more vibrant sketch and also HDR images. To use a HDR canvas you will need to create it using the P2DHDR constant like below:

function setup(){
  createCanvas(400, 400, P2DHDR);
}

When a P2DHDR canvas is created, the default color mode will be switched to the new RGBHDR color mode instead of RGB. In practice you can continue to use the same RGB color definition you have always used.

function setup(){
  createCanvas(400, 400, P2DHDR);
}

function draw(){
  background(255, 0, 0);
  fill(100, 255, 0);
  circle(100, 100, 50);
}

This example sketch shows a direct comparison between HDR and non-HDR colors, you should see three bands of red, green, and blue colors with a slightly dimmer red, green, and blue circles within. However, both your browser and your screen will need to support HDR to see the difference. Currently Firefox on desktop does not support HDR canvas so if you do not see a difference, try a different browser such as Safari or Chrome.

You can also now load HDR images and have them be displayed in full HDR in a HDR canvas. If you see a dark image on the linked sketch, your browser or screen does not support HDR and you should try a different browser/device.

A new simple lines mode for WebGL (thanks to contributions from @perminder-17)

If you are drawing lots of shapes, and don't need stroke caps or joins, you can use a simple lines mode for increased performance in WebGL. You can activate this mode by calling linesMode(SIMPLE) in your sketch.

Custom shaders for fills, strokes, images (thanks to @Garima3110 and @perminder-17)

You can now create your own shaders for fills, strokes, and images, and have them all applied at once! Use shader() to set a fill shader, strokeShader() to set a stroke shader, and imageShader() to set an image shader. Try using baseMaterialShader().modify(...) and baseStrokeShader().modify(...) to create custom shaders.

let myFillShader = baseMaterialShader.modify({
  'vec4 getFinalColor': `(vec4 color) {
    return vec4(1., 1., 0., 1.);
  }`
});
let myStrokeShader = baseStrokeShader.modify({
  'vec4 getFinalColor': `(vec4 color) {
    return vec4(1., 0., 1., 1.);
  }`
});
let myImageShader = baseMaterialShader.modify({
  'vec4 getFinalColor': `(vec4 color) {
    return vec4(0., 1., 1., 1.);
  }`
});

shader(myFillShader);
strokeShader(myStrokeShader);
imageShader(myImageShader);

sphere(); // Draws with the custom stroke and image shaders
image(myImg, 0, 0); // Draws with the custom image shader

Updated bezier and curve drawing functions (thanks to @GregStanton)

First off: you can combine multiple types of curves in one begin/endShape() block now!

Long cubic and quadratic bezier vertex calls are now split up into their individual control points. Both cubic and quadratic curves are done with bezierVertex now, and you can set bezierOrder() to change from cubic (order 3) to quadratic (order 2). For WebGL mode, this also means you can also specify texture coordinates per control point, or change the fill, stroke, normal, and more between control points.

1.x2.0
beginShape();
vertex(10, 10);
vertex(30, 10);

bezierVertex(35, 10, 40, 15, 40, 20);

vertex(40, 30);

quadraticVertex(40, 40, 30, 40);

vertex(10, 40);

endShape(CLOSE);
beginShape();
vertex(10, 10);
vertex(30, 10);

// Default cubic
bezierVertex(35, 10);
bezierVertex(40, 15);
bezierVertex(40, 20);

vertex(40, 30);

bezierOrder(2);
bezierVertex(40, 40);
bezierVertex(30, 40);

vertex(10, 40);

endShape(p5.CLOSE);

We've renamed curveVertex to splineVertex and have given it more options. By default, it will now go through every splineVertex, so you no longer have to double up the first/last point to get it to go through it:

1.x2.0
beginShape();
curveVertex(10, 10);
curveVertex(10, 10);
curveVertex(15, 40);
curveVertex(40, 35);
curveVertex(25, 15);
curveVertex(15, 25);
curveVertex(15, 25);
endShape();
beginShape();

splineVertex(10, 10);
splineVertex(15, 40);
splineVertex(40, 35);
splineVertex(25, 15);
splineVertex(15, 25);

endShape();

Similarly, endShape(CLOSE) (or endContour(CLOSE) if you're in a contour) will cause a spline to smoothly loop back on itself so you no longer need to double up any points:

1.x2.0
beginShape();
curveVertex(15, 25);
curveVertex(10, 10);
curveVertex(15, 40);
curveVertex(40, 35);
cu...
Read more

v1.11.5

17 Apr 16:44
Compare
Choose a tag to compare

This release is published on npm with the tag r1

What's Changed

What's Changed 🎊

  • reorder npm run commands to make p5.js-website update the correct ver… by @lirenjie95 in #7747
  • Update README.md - 2.0 Info by @ksen0 in #7751

Full Changelog: v1.11.4...v1.11.5

v1.11.4

16 Apr 09:14
Compare
Choose a tag to compare

What's Changed

What's Changed 🎊

New Contributors

Full Changelog: v1.11.3...v1.11.4

v2.0.0-beta.8

15 Apr 23:11
ecbb4d5
Compare
Choose a tag to compare
v2.0.0-beta.8 Pre-release
Pre-release

What's Changed

What's Changed 🎊

Full Changelog: v2.0.0-beta.7...v2.0.0-beta.8

v2.0.0-beta.7

10 Apr 13:51
Compare
Choose a tag to compare
v2.0.0-beta.7 Pre-release
Pre-release

What's Changed

What's Changed 🎊

Full Changelog: v2.0.0-beta.6...v2.0.0-beta.7

v2.0.0-beta.6

08 Apr 15:59
Compare
Choose a tag to compare
v2.0.0-beta.6 Pre-release
Pre-release

What's Changed

What's Changed 🎊

New Contributors

Full Changelog: v2.0.0-beta.5...v2.0.0-beta.6

v2.0.0-beta.5

22 Mar 18:15
214e7b3
Compare
Choose a tag to compare
v2.0.0-beta.5 Pre-release
Pre-release

What's Changed

What's Changed 🎊

Full Changelog: v2.0.0-beta.4...v2.0.0-beta.5

v2.0.0-beta.4

03 Mar 15:00
Compare
Choose a tag to compare
v2.0.0-beta.4 Pre-release
Pre-release

The library is available from JSDelivr:

You can duplicate this p5.js web editor project: https://editor.p5js.org/limzykenneth/sketches/FF4krBr6P

You can also import p5 directly from NPM as an ESM module. More documentation on ESM usage to come.

What's Changed

What's Changed 🎊

Full Changelog: v2.0.0-beta.3...v2.0.0-beta.4

v2.0.0-beta.3

25 Feb 21:27
259a4f7
Compare
Choose a tag to compare
v2.0.0-beta.3 Pre-release
Pre-release

This release has been pulled as it was published incorrectly on NPM. Please use 2.0.0-beta.4 onwards instead. The release will be kept here for the release notes but the version will be pulled on NPM.

The library is available from JSDelivr:

* p5.js - https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.js
* p5.min.js - https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.min.js

You can duplicate this p5.js web editor project: https://editor.p5js.org/davepagurek/sketches/RwD_DbVR7

You can also import p5 directly from NPM as an ESM module. More documentation on ESM usage to come.

What's Changed

What's Changed 🎊

New Contributors

Full Changelog: v2.0.0-beta.2...v2.0.0-beta.3

v2.0.0-beta.2

02 Feb 22:21
fbb9e41
Compare
Choose a tag to compare
v2.0.0-beta.2 Pre-release
Pre-release

The library is available from JSDelivr:

You can duplicate this p5.js web editor project: https://editor.p5js.org/davepagurek/sketches/RwD_DbVR7

You can also import p5 directly from NPM as an ESM module. More documentation on ESM usage to come.

What's Changed

  • Merged main into 2.0
  • Fix bug where pixels is not available
  • Fixed model() not working inside buildGeometry()
  • Fixed WebGL text alignment bugs
  • Fixed bugs in closed splines

What to test

Async loading (thanks to @limzykenneth)

Rather than having a preload function, p5 2.0 has async setup!

1.x2.0
let img;

function preload() {
  img = loadImage('cat.jpg');
}

function setup() {
  createCanvas(200, 200);
}
let img;

async function setup() {
  createCanvas(200, 200);
  img = await loadImage('cat.jpg');
}

🚧 Since this is a breaking change from 1.x to 2.0, you can weight in on the compatibility discussion here

Support for loading fonts via CSS (thanks to @dhowe)

In 2D mode, try loading fonts via a a path to a CSS font file, such as a Google Fonts link!

loadFont("https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,[email protected],200..800&display=swap")
loadFont(`@font-face { font-family: "Bricolage Grotesque", serif; font-optical-sizing: auto; font-weight: <weight> font-style: normal; font-variation-settings: "wdth" 100; }`);
loadFont({
    fontFamily: '"Bricolage Grotesque", serif',
    fontOpticalSizing: 'auto',
    fontWeight: '<weight>',
    fontStyle: 'normal',
    fontVariationSettings: '"wdth" 100',
});
loadFont("https://fonts.gstatic.com/s/inter/v18/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuLyfMZhrib2Bg-4.ttf");
loadFont("path/to/localFont.ttf");
loadFont("system-font-name");

Support for variable font weight (thanks to contributions by @dhowe)

In 2D mode, if you've loaded a variable font, try changing its weight!

var font;

async function setup() {
  createCanvas(100, 100);
  font = await loadFont(
    'https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap'
  );
}

function draw() {
  background(255);
  textFont(font);
  textAlign(LEFT, TOP);
  textSize(35);
  textWeight(sin(millis() * 0.002) * 200 + 400);
  text('p5*js', 0, 10);
}

More ways to draw and manipulate text (thanks to @davepagurek)

Like how textToPoints() gives you points on text, the new textToContours() function lets you edit the points on text and then draw them with fills!

createCanvas(100, 100);
const font = await loadFont('myFont.ttf');
background(200);
strokeWeight(2);
textSize(50);
const contours = font.textToContours('p5*js', 0, 50, { sampleFactor: 0.5 });
beginShape();
for (const pts of contours) {
  beginContour();
  for (const pt of pts) {
    vertex(pt.x + 20*sin(pt.y*0.01), pt.y + 20*sin(pt.x*0.01));
  }
  endContour(CLOSE);
}
endShape();

In WebGL, you can use textToModel to extrude a 3D model out of your text:

createCanvas(100, 100, WEBGL);
const font = await loadFont('myFont.ttf');
background(200);
textSize(50);
const geom = font.textToModel('p5*js', 0, 50, { sampleFactor: 2, extrude: 20 });
orbitControl();
model(geom);

A new pointer event handling system (thanks to @diyaayay)

Instead of having separate methods for mouse and touch, we now use the browser's pointer API to handle both simultaneously. Try defining mouse functions as usual and accessing the global touches array to see what pointers are active for multitouch support!

Custom shader attributes (thanks to @lukeplowden)

If you are using a shader and want custom per-vertex properties in addition to uniforms, which are the same across the whole shape, you can now call vertexProperty(name, value) before vertices.

const vertSrc = `#version 300 es
 precision mediump float;
 uniform mat4 uModelViewMatrix;
 uniform mat4 uProjectionMatrix;

 in vec3 aPosition;
 in vec2 aOffset;

 void main(){
   vec4 positionVec4 = vec4(aPosition.xyz, 1.0);
   positionVec4.xy += aOffset;
   gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;
 }
`;

const fragSrc = `#version 300 es
 precision mediump float;
 out vec4 outColor;
 void main(){
   outColor = vec4(0.0, 1.0, 1.0, 1.0);
 }
`;

function setup(){
  createCanvas(100, 100, WEBGL);

  // Create and use the custom shader.
  const myShader = createShader(vertSrc, fragSrc);
  shader(myShader);

  describe('A wobbly, cyan circle on a gray background.');
}

function draw(){
  // Set the styles
  background(125);
  noStroke();

  // Draw the circle.
  beginShape();
  for (let i = 0; i < 30; i++){
    const x = 40 * cos(i/30 * TWO_PI);
    const y = 40 * sin(i/30 * TWO_PI);

    // Apply some noise to the coordinates.
    const xOff = 10 * noise(x + millis()/1000) - 5;
    const yOff = 10 * noise(y + millis()/1000) - 5;

    // Apply these noise values to the following vertex.
    vertexProperty('aOffset', [xOff, yOff]);
    vertex(x, y);
  }
  endShape(CLOSE);
}

Updated bezier and curve drawing functions (thanks to @GregStanton)

First off: you can combine multiple types of curves in one begin/endShape() block now!

Long cubic and quadratic bezier vertex calls are now split up into their individual control points. Both cubic and quadratic curves are done with bezierVertex now, and you can set bezierOrder() to change from cubic (order 3) to quadratic (order 2). For WebGL mode, this also means you can also specify texture coordinates per control point, or change the fill, stroke, normal, and more between control points.

1.x2.0
beginShape();
vertex(10, 10);
vertex(30, 10);

bezierVertex(35, 10, 40, 15, 40, 20);

vertex(40, 30);

quadraticVertex(40, 40, 30, 40);

vertex(10, 40);

endShape(CLOSE);
beginShape();
vertex(10, 10);
vertex(30, 10);

// Default cubic
bezierVertex(35, 10);
bezierVertex(40, 15);
bezierVertex(40, 20);

vertex(40, 30);

bezierOrder(2);
bezierVertex(40, 40);
bezierVertex(30, 40);

vertex(10, 40);

endShape(p5.CLOSE);

We've renamed curveVertex to splineVertex and have given it more options. By default, it will now go through every splineVertex, so you no longer have to double up the first/last point to get it to go through it:

1.x2.0
beginShape();
curveVertex(10, 10);
curveVertex(10, 10);
curveVertex(15, 40);
curveVertex(40, 35);
curveVertex(25, 15);
curveVertex(15, 25);
curveVertex(15, 25);
endShape();
beginShape();

splineVertex(10, 10);
splineVertex(15, 40);
splineVertex(40, 35);
splineVertex(25, 15);
splineVertex(15, 25);

endShape();

Similarly, endShape(CLOSE) (or endContour(CLOSE) if you're in a contour) will cause a spline to smoothly loop back on itself so you no longer need to double up any points:

1.x2.0
beginShape();
curveVertex(15, 25);
curveVertex(10, 10);
curveVertex(15, 40);
curveVertex(40, 35);
curveVertex(25, 15);
curveVertex(15, 25);
curveVertex(10, 10);
curveVertex(15, 40);
endShape();
beginShape();

splineVertex(10, 10);
splineVertex(15, 40);
splineVertex(40, 35);
splineVertex(25, 15);
splineVertex(15, 25);


endShape(CLOSE);

🚧 Since this is a breaking change from 1.x to 2.0, you can weight in on the compatibility discussion here

A new simple lines mode for WebGL (thanks to contributions from @perminder-17)

If you are drawing lots of shapes, and don't need stroke caps or joins, you can use a simple lines mode for increased performance in WebGL. You can activate this mode by calling linesMode(SIMPLE) in your sketch.

Custom shaders for fills, strokes, images (thanks to @Garima3110 and @perminder-17)

You can now create your own shaders for fills, strokes, and images, and have them all applied at once! Use shader() to set a fill shader, strokeShader() to set a stroke shader, and imageShader() to set an image shader. Try using baseMaterialShader().modify(...) and baseStrokeShader().modify(...) to create custom shaders.

let myFillShader = baseMaterialShader.modify({
  'vec4 getFinalColor': `(vec4 color) {
    return vec4(1., 1., 0., 1.);
  }`
});
let myStrokeShader = baseStrokeShader.modify({
  'vec4 getFinalColor': `(vec4 color) {
    return vec4(1., 0., 1., 1.);
  }`
});
let myImageShader = baseMaterialShader.modify({
  'vec4 getFinalColor': `(vec4 color) {
    return vec4(0., 1., 1., 1.);
  }`
});

shader(myFillShader);
strokeShader(myStrokeShader);
imageShader(myImageShader);

sphere(); // Draws with the custom stroke and image shaders
image(myImg, 0, 0); // Draws with the custom image shader

A new public p5.Matrix class (thanks to @holomorfo)

TODO add examples

Support for more color spaces in p5.Color (thanks to @limzykenneth and @dianamgalindo)

p5.js 2.0 now supports more color modes in addition to the existing RGB, HSB, and HSL color modes. Here are the list of new supported color mode and brief description of them:

  • RGBHDR - High Dynamic Range RGB color defined within the Display P3 color space. You will...
Read more