Colours in p5
I will note that it is "standard practice" to use American spellings for words like "colour" in the domain of computer science. However, I can't quite bring myself to spell it "color" unless I absolutely need to. Official javascript and p5 use the spelling "color", and when I have a choice about how to spell it, I usually choose to spell it "colour".
Using colour
Many p5 functions take a colour as their argument, perhaps the most common being fill ()
and background ()
. These functions, as well as p5's color ()
function, which returns a color
object, offer a variety of ways to deal with colour - different paradigms which work slightly differently.
All paradigms are 8-bit, which means, as a rule, they operate in values between 0
- 255
. The exception is HSB
, which we will discuss later in the post, and colour keywords.
Keywords
Many colours can be passed into color ()
, fill ()
, or background ()
, as strings. Some current favourites of mine are 'turquoise'
and 'hotpink'
:
Just be sure to remember to put quotation marks around them, so javascript knows to treat them as a string, rather than as a variable. You can find a list of colour keywords here.
Greyscale
Giving one numerical argument to color ()
, fill ()
, or background ()
will result in a greyscale colour: 0
yields black, 255
yields white, and all the values in between yield various shades of grey.
Consider the following sketch:
function setup () {
createCanvas (450, 150)
frameRate (16)
textAlign (CENTER, CENTER)
textSize (64)
noStroke ()
}
function draw() {
// shade iterates with frameCount
const shade = frameCount % 256
// set the background colour
// with the value in shade
background (shade)
fill (255) // white text
text (shade, 150, 75) // display value of shade
fill (0) // black text
text (shade, 300, 75) // display value of shade
}
Greyscale + Alpha
Giving color ()
, fill ()
, or background ()
two arguments will specify greyscale and alpha values. Alpha represents how opaque a colour is, and low alpha values make the colour more transparent.
Consider the following sketch:
let shade // declaring shade in the global scope
// so it will persist between frames
function setup () {
createCanvas (450, 150)
frameRate (16)
rectMode (CENTER)
textAlign (CENTER, CENTER)
textSize (64)
noStroke ()
shade = rand_256 ()
}
function draw() {
// alph iterates with frameCount
const alph = frameCount % 256
if (alph == 0) {
// when alph resets to 0
// reassign to shade
// a random value between 0-255
shade = rand_256 ()
}
// draw the square first
square (300, 77, 75)
// draw the background over the square
// with the greyscale and alpha values
background (shade, alph)
fill (`hotpink`) // white text
text (alph, 150, 75) // display value of alph
}
function rand_256 () {
const r = random (256) // generate a random value
// between 0-255
return floor (r) // chop off any decimal places
// & return the integer
}
Here the background is being drawn over the top of the pink square on the right, which is why, when alph
values get close to 255
, the pink square disappears.
Also note that at low values for alph
, because the colour is quite transparent, when the background is drawn, it does not hide the content already on the canvas. Trails, or echos, of previous frames remain visible, which clear up as alph
values approach 255
and the background becomes more opaque.
RGB: Red, Green, Blue
Giving color ()
, fill ()
, or background ()
three arguments will specify a red, green, and blue values, each, again, between 0
- 255
.
Cosider the following sketch.
The number represents the red value in the first square, the green value in the second, and the blue value in the third. The other values are static while the numbers increase, and then randomised when the numbers reset. View the code here.
Consider the following code:
function setup () {
createCanvas (400, 400)
frameRate (2)
noStroke ()
}
function draw () {
background (220)
for (let y = 0; y < height; y += 20) {
for (let x = 0; x < width; x += 20) {
fill (rand_colour ())
square (x, y, 20)
}
}
}
function rand_colour () {
const r = floor (random (256))
const g = floor (random (256))
const b = floor (random (256))
return color (r, g, b)
}
Note the function at the bottom - random integer values between 0
- 255
are chosen for variables r
, g
, and b
. Those values are then passed to the constructor method color ()
which returns a p5 color
object, which is then returned by the function.
You can see it being used to generate random colours for the fill ()
function in the nested for loops, which generate the 20 x 20 grid rendered to the canvas:
RGBA: Red, Green, Blue, & Alpha
Passing four values in to color ()
, fill ()
, or background ()
will signal to p5 that you wish to use RGBA mode - the fourth value indicating the alpha, or opacity, again between 0
- 255
.
The following sketch is similar to the last sketch, but the alpha values of the randomly generated colours are being modulated by a sinusoid, periodically revealing the image drawn underneath:
View the code here.
HSB: Hue, Saturation, and Brightness
We can change how p5 interprets the values we pass into color ()
, fill ()
, and background ()
by switching colour mode. The default mode p5 starts in is RGB
, but we can switch to HSB
mode by calling colorMode (HSB)
.
In HSB
mode, the first argument is the hue, interpreted as an angle between 0
- 360
that travels around a hue circle.
At 0°, the hue is red. At 360°, the hue returns to red. Between 0° and 360°, the hue transforms through all the colours of the rainbow. Click on the p5 canvas below:
The second argument, saturation, operates between 0
- 100
.
The third argument, brightness, also operates between 0
- 100
.
Note that in HSB mode, alpha, the fourth (or second) argument, operates at values between 0
- 1
, rather than 0
- 255
.
lerpColor
The lerpColor ()
function lets you morph smoothly between colours. It takes two colours and a value between 0
- 1
as arguments, and returns a third colour:
You can read more about lerpColor ()
here.